*/
/*
* This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
*
* lustre/utils/gss/lgss_keyring.c
*
if (param.status) {
logmsg(LL_ERR, "status: %ld (%s)\n",
param.status, strerror((int)(-param.status)));
-
- /* kernel return -ETIMEDOUT means the rpc timedout, we should
- * notify the caller to reinitiate the gss negotiation, by
- * returning -ERESTART
- */
- if (param.status == -ETIMEDOUT)
- rc = -ERESTART;
- else
- rc = param.status;
- return rc;
+ return param.status;
}
p = (unsigned int *)outbuf;
if (lnd->lnd_rpc_err) {
logmsg(LL_ERR, "negotiation rpc error: %d\n",
lnd->lnd_rpc_err);
- return -1;
+ return lnd->lnd_rpc_err;
}
if (gr.gr_major != GSS_S_COMPLETE &&
logmsg(LL_ERR, "negotiation gss error %x\n",
lnd->lnd_gss_err);
- return -1;
+ return -ENOTCONN;
}
if (gr.gr_ctx.length != 0) {
struct keyring_upcall_param *kup,
int req_fd[2], int reply_fd[2])
{
- struct lgss_nego_data lnd;
- OM_uint32 min_stat;
- int rc = -1;
-
- memset(&lnd, 0, sizeof(lnd));
+ struct lgss_nego_data lnd;
+ OM_uint32 min_stat;
+ int rc = -1;
+ bool redo = true;
if (lgss_get_service_str(&g_service, kup->kup_svc, kup->kup_nid)) {
logmsg(LL_ERR, "key %08x: failed to construct service "
goto out_cred;
}
+retry_nego:
+ memset(&lnd, 0, sizeof(lnd));
if (lgssc_init_nego_data(&lnd, kup, cred->lc_mech->lmt_mech_n)) {
logmsg(LL_ERR, "key %08x: failed to initialize "
"negotiation data\n", keyid);
}
rc = lgssc_negotiation(&lnd, req_fd, reply_fd);
- if (rc) {
+ if (rc == -EAGAIN || (rc == -ETIMEDOUT && redo)) {
+ logmsg(LL_ERR, "Failed negotiation must retry\n");
+ redo = false;
+ goto retry_nego;
+ } else if (rc) {
logmsg(LL_ERR, "key %08x: failed to negotiation\n", keyid);
error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
goto out;
struct keyring_upcall_param *kup,
int req_fd[2], int reply_fd[2])
{
- struct lgss_nego_data lnd;
- OM_uint32 min_stat;
- int rc;
-
-retry:
- memset(&lnd, 0, sizeof(lnd));
+ struct lgss_nego_data lnd;
+ OM_uint32 min_stat;
+ int rc;
+ bool redo = true;
rc = lgss_get_service_str(&g_service, kup->kup_svc, kup->kup_nid);
if (rc) {
goto out_cred;
}
+retry:
+ memset(&lnd, 0, sizeof(lnd));
rc = lgssc_init_nego_data(&lnd, kup, cred->lc_mech->lmt_mech_n);
if (rc) {
logmsg(LL_ERR, "key %08x: failed to initialize "
* update to the kernel key
*/
rc = lgssc_negotiation_manual(&lnd, cred, req_fd, reply_fd);
- if (rc == -EAGAIN) {
+ if (rc == -EAGAIN || (rc == -ETIMEDOUT && redo)) {
logmsg(LL_ERR, "Failed negotiation must retry\n");
+ redo = false;
goto retry;
-
} else if (rc) {
logmsg(LL_ERR, "key %08x: failed to negotiate\n", keyid);
error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
data[6], data[7], data[8], data[9], data[10]);
uparam->kup_secid = strtol(data[0], NULL, 0);
- strlcpy(uparam->kup_mech, data[1], sizeof(uparam->kup_mech));
+ snprintf(uparam->kup_mech, sizeof(uparam->kup_mech), "%s", data[1]);
uparam->kup_uid = strtol(data[2], NULL, 0);
uparam->kup_gid = strtol(data[3], NULL, 0);
if (strchr(data[4], 'r'))
uparam->kup_svc_type = data[5][0];
uparam->kup_svc = strtol(data[6], NULL, 0);
uparam->kup_nid = strtoll(data[7], NULL, 0);
- strlcpy(uparam->kup_tgt, data[8], sizeof(uparam->kup_tgt));
+ snprintf(uparam->kup_tgt, sizeof(uparam->kup_tgt), "%s", data[8]);
uparam->kup_selfnid = strtoll(data[9], NULL, 0);
uparam->kup_pid = strtol(data[10], NULL, 0);
static int associate_with_ns(char *path)
{
-#ifdef HAVE_SETNS
int fd, rc = -1;
fd = open(path, O_RDONLY);
}
return rc;
-#else
- return -1;
-#endif /* HAVE_SETNS */
}
static int prepare_and_instantiate(struct lgss_cred *cred, key_serial_t keyid,
char path[PATH_MAX] = "";
int other_ns = 0;
int rc = 0;
-#ifdef HAVE_SETNS
struct stat parent_ns = { .st_ino = 0 };
struct stat caller_ns = { .st_ino = 0 };
-#endif
set_log_level();
cred->lc_svc_type = uparam.kup_svc_type;
cred->lc_self_nid = uparam.kup_selfnid;
-#ifdef HAVE_SETNS
/* Is caller in different namespace? */
- snprintf(path, sizeof(path), "/proc/%d/ns/mnt", getpid());
- if (stat(path, &parent_ns))
- logmsg(LL_ERR, "cannot stat %s: %s\n", path, strerror(errno));
- snprintf(path, sizeof(path), "/proc/%d/ns/mnt", uparam.kup_pid);
- if (stat(path, &caller_ns))
- logmsg(LL_ERR, "cannot stat %s: %s\n", path, strerror(errno));
- if (caller_ns.st_ino != parent_ns.st_ino) {
- other_ns = 1;
+ /* If passed caller's pid is 0, it means we have to stick
+ * with current namespace.
+ */
+ if (uparam.kup_pid) {
+ snprintf(path, sizeof(path), "/proc/%d/ns/mnt", getpid());
+ if (stat(path, &parent_ns)) {
+ logmsg(LL_DEBUG, "cannot stat %s: %s\n",
+ path, strerror(errno));
+ } else {
+ snprintf(path, sizeof(path), "/proc/%d/ns/mnt",
+ uparam.kup_pid);
+ if (stat(path, &caller_ns))
+ logmsg(LL_DEBUG, "cannot stat %s: %s\n",
+ path, strerror(errno));
+ else if (caller_ns.st_ino != parent_ns.st_ino)
+ other_ns = 1;
+ }
}
-#endif /* HAVE_SETNS */
/*
* if caller's namespace is different, fork a child and associate it
* with caller's namespace to do credentials preparation
*/
if (other_ns) {
- logmsg(LL_TRACE, "caller's namespace is diffent\n");
+ logmsg(LL_TRACE, "caller's namespace is different\n");
/* use pipes to pass info between child and parent processes */
if (pipe(req_fd) == -1) {
close(reply_fd[1]);
return rc;
} else {
- logmsg(LL_TRACE, "caller's namespace is the same\n");
+ if (uparam.kup_pid)
+ logmsg(LL_TRACE, "caller's namespace is the same\n");
+ else
+ logmsg(LL_TRACE, "stick with current namespace\n");
rc = prepare_and_instantiate(cred, keyid, uparam.kup_uid);
if (rc != 0)