|
@@ -98,7 +98,7 @@ static struct kmem_cache *odstate_slab;
|
|
|
|
|
|
static void free_session(struct nfsd4_session *);
|
|
|
|
|
|
-static struct nfsd4_callback_ops nfsd4_cb_recall_ops;
|
|
|
+static const struct nfsd4_callback_ops nfsd4_cb_recall_ops;
|
|
|
|
|
|
static bool is_session_dead(struct nfsd4_session *ses)
|
|
|
{
|
|
@@ -1857,15 +1857,28 @@ static void copy_clid(struct nfs4_client *target, struct nfs4_client *source)
|
|
|
target->cl_clientid.cl_id = source->cl_clientid.cl_id;
|
|
|
}
|
|
|
|
|
|
-static int copy_cred(struct svc_cred *target, struct svc_cred *source)
|
|
|
+int strdup_if_nonnull(char **target, char *source)
|
|
|
{
|
|
|
- if (source->cr_principal) {
|
|
|
- target->cr_principal =
|
|
|
- kstrdup(source->cr_principal, GFP_KERNEL);
|
|
|
- if (target->cr_principal == NULL)
|
|
|
+ if (source) {
|
|
|
+ *target = kstrdup(source, GFP_KERNEL);
|
|
|
+ if (!*target)
|
|
|
return -ENOMEM;
|
|
|
} else
|
|
|
- target->cr_principal = NULL;
|
|
|
+ *target = NULL;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int copy_cred(struct svc_cred *target, struct svc_cred *source)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = strdup_if_nonnull(&target->cr_principal, source->cr_principal);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ ret = strdup_if_nonnull(&target->cr_raw_principal,
|
|
|
+ source->cr_raw_principal);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
target->cr_flavor = source->cr_flavor;
|
|
|
target->cr_uid = source->cr_uid;
|
|
|
target->cr_gid = source->cr_gid;
|
|
@@ -1969,6 +1982,9 @@ static bool mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp)
|
|
|
return false;
|
|
|
if (!svc_rqst_integrity_protected(rqstp))
|
|
|
return false;
|
|
|
+ if (cl->cl_cred.cr_raw_principal)
|
|
|
+ return 0 == strcmp(cl->cl_cred.cr_raw_principal,
|
|
|
+ cr->cr_raw_principal);
|
|
|
if (!cr->cr_principal)
|
|
|
return false;
|
|
|
return 0 == strcmp(cl->cl_cred.cr_principal, cr->cr_principal);
|
|
@@ -2240,7 +2256,8 @@ nfsd4_store_cache_entry(struct nfsd4_compoundres *resp)
|
|
|
base = resp->cstate.data_offset;
|
|
|
slot->sl_datalen = buf->len - base;
|
|
|
if (read_bytes_from_xdr_buf(buf, base, slot->sl_data, slot->sl_datalen))
|
|
|
- WARN("%s: sessions DRC could not cache compound\n", __func__);
|
|
|
+ WARN(1, "%s: sessions DRC could not cache compound\n",
|
|
|
+ __func__);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -2365,10 +2382,27 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
|
|
|
if (exid->flags & ~EXCHGID4_FLAG_MASK_A)
|
|
|
return nfserr_inval;
|
|
|
|
|
|
+ new = create_client(exid->clname, rqstp, &verf);
|
|
|
+ if (new == NULL)
|
|
|
+ return nfserr_jukebox;
|
|
|
+
|
|
|
switch (exid->spa_how) {
|
|
|
case SP4_MACH_CRED:
|
|
|
- if (!svc_rqst_integrity_protected(rqstp))
|
|
|
- return nfserr_inval;
|
|
|
+ if (!svc_rqst_integrity_protected(rqstp)) {
|
|
|
+ status = nfserr_inval;
|
|
|
+ goto out_nolock;
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * Sometimes userspace doesn't give us a principal.
|
|
|
+ * Which is a bug, really. Anyway, we can't enforce
|
|
|
+ * MACH_CRED in that case, better to give up now:
|
|
|
+ */
|
|
|
+ if (!new->cl_cred.cr_principal &&
|
|
|
+ !new->cl_cred.cr_raw_principal) {
|
|
|
+ status = nfserr_serverfault;
|
|
|
+ goto out_nolock;
|
|
|
+ }
|
|
|
+ new->cl_mach_cred = true;
|
|
|
case SP4_NONE:
|
|
|
break;
|
|
|
default: /* checked by xdr code */
|
|
@@ -2377,10 +2411,6 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
|
|
|
return nfserr_encr_alg_unsupp;
|
|
|
}
|
|
|
|
|
|
- new = create_client(exid->clname, rqstp, &verf);
|
|
|
- if (new == NULL)
|
|
|
- return nfserr_jukebox;
|
|
|
-
|
|
|
/* Cases below refer to rfc 5661 section 18.35.4: */
|
|
|
spin_lock(&nn->client_lock);
|
|
|
conf = find_confirmed_client_by_name(&exid->clname, nn);
|
|
@@ -2442,7 +2472,6 @@ out_new:
|
|
|
goto out;
|
|
|
}
|
|
|
new->cl_minorversion = cstate->minorversion;
|
|
|
- new->cl_mach_cred = (exid->spa_how == SP4_MACH_CRED);
|
|
|
|
|
|
gen_clid(new, nn);
|
|
|
add_to_unconfirmed(new);
|
|
@@ -2460,6 +2489,7 @@ out_copy:
|
|
|
|
|
|
out:
|
|
|
spin_unlock(&nn->client_lock);
|
|
|
+out_nolock:
|
|
|
if (new)
|
|
|
expire_client(new);
|
|
|
if (unconf)
|
|
@@ -3648,7 +3678,7 @@ static void nfsd4_cb_recall_release(struct nfsd4_callback *cb)
|
|
|
nfs4_put_stid(&dp->dl_stid);
|
|
|
}
|
|
|
|
|
|
-static struct nfsd4_callback_ops nfsd4_cb_recall_ops = {
|
|
|
+static const struct nfsd4_callback_ops nfsd4_cb_recall_ops = {
|
|
|
.prepare = nfsd4_cb_recall_prepare,
|
|
|
.done = nfsd4_cb_recall_done,
|
|
|
.release = nfsd4_cb_recall_release,
|
|
@@ -4541,8 +4571,7 @@ static void
|
|
|
laundromat_main(struct work_struct *laundry)
|
|
|
{
|
|
|
time_t t;
|
|
|
- struct delayed_work *dwork = container_of(laundry, struct delayed_work,
|
|
|
- work);
|
|
|
+ struct delayed_work *dwork = to_delayed_work(laundry);
|
|
|
struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
|
|
|
laundromat_work);
|
|
|
|