Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'nfsd-5.2' of git://linux-nfs.org/~bfields/linux

Pull nfsd updates from Bruce Fields:
"This consists mostly of nfsd container work:

Scott Mayhew revived an old api that communicates with a userspace
daemon to manage some on-disk state that's used to track clients
across server reboots. We've been using a usermode_helper upcall for
that, but it's tough to run those with the right namespaces, so a
daemon is much friendlier to container use cases.

Trond fixed nfsd's handling of user credentials in user namespaces. He
also contributed patches that allow containers to support different
sets of NFS protocol versions.

The only remaining container bug I'm aware of is that the NFS reply
cache is shared between all containers. If anyone's aware of other
gaps in our container support, let me know.

The rest of this is miscellaneous bugfixes"

* tag 'nfsd-5.2' of git://linux-nfs.org/~bfields/linux: (23 commits)
nfsd: update callback done processing
locks: move checks from locks_free_lock() to locks_release_private()
nfsd: fh_drop_write in nfsd_unlink
nfsd: allow fh_want_write to be called twice
nfsd: knfsd must use the container user namespace
SUNRPC: rsi_parse() should use the current user namespace
SUNRPC: Fix the server AUTH_UNIX userspace mappings
lockd: Pass the user cred from knfsd when starting the lockd server
SUNRPC: Temporary sockets should inherit the cred from their parent
SUNRPC: Cache the process user cred in the RPC server listener
nfsd: Allow containers to set supported nfs versions
nfsd: Add custom rpcbind callbacks for knfsd
SUNRPC: Allow further customisation of RPC program registration
SUNRPC: Clean up generic dispatcher code
SUNRPC: Add a callback to initialise server requests
SUNRPC/nfs: Fix return value for nfs4_callback_compound()
nfsd: handle legacy client tracking records sent by nfsdcld
nfsd: re-order client tracking method selection
nfsd: keep a tally of RECLAIM_COMPLETE operations when using nfsdcld
nfsd: un-deprecate nfsdcld
...

+1086 -317
+2 -2
fs/lockd/clntlock.c
··· 56 56 u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4; 57 57 int status; 58 58 59 - status = lockd_up(nlm_init->net); 59 + status = lockd_up(nlm_init->net, nlm_init->cred); 60 60 if (status < 0) 61 61 return ERR_PTR(status); 62 62 ··· 241 241 allow_signal(SIGKILL); 242 242 243 243 down_write(&host->h_rwsem); 244 - lockd_up(net); /* note: this cannot fail as lockd is already running */ 244 + lockd_up(net, NULL); /* note: this cannot fail as lockd is already running */ 245 245 246 246 dprintk("lockd: reclaiming locks for host %s\n", host->h_name); 247 247
+20 -13
fs/lockd/svc.c
··· 188 188 189 189 static int create_lockd_listener(struct svc_serv *serv, const char *name, 190 190 struct net *net, const int family, 191 - const unsigned short port) 191 + const unsigned short port, 192 + const struct cred *cred) 192 193 { 193 194 struct svc_xprt *xprt; 194 195 195 196 xprt = svc_find_xprt(serv, name, net, family, 0); 196 197 if (xprt == NULL) 197 198 return svc_create_xprt(serv, name, net, family, port, 198 - SVC_SOCK_DEFAULTS); 199 + SVC_SOCK_DEFAULTS, cred); 199 200 svc_xprt_put(xprt); 200 201 return 0; 201 202 } 202 203 203 204 static int create_lockd_family(struct svc_serv *serv, struct net *net, 204 - const int family) 205 + const int family, const struct cred *cred) 205 206 { 206 207 int err; 207 208 208 - err = create_lockd_listener(serv, "udp", net, family, nlm_udpport); 209 + err = create_lockd_listener(serv, "udp", net, family, nlm_udpport, 210 + cred); 209 211 if (err < 0) 210 212 return err; 211 213 212 - return create_lockd_listener(serv, "tcp", net, family, nlm_tcpport); 214 + return create_lockd_listener(serv, "tcp", net, family, nlm_tcpport, 215 + cred); 213 216 } 214 217 215 218 /* ··· 225 222 * Returns zero if all listeners are available; otherwise a 226 223 * negative errno value is returned. 227 224 */ 228 - static int make_socks(struct svc_serv *serv, struct net *net) 225 + static int make_socks(struct svc_serv *serv, struct net *net, 226 + const struct cred *cred) 229 227 { 230 228 static int warned; 231 229 int err; 232 230 233 - err = create_lockd_family(serv, net, PF_INET); 231 + err = create_lockd_family(serv, net, PF_INET, cred); 234 232 if (err < 0) 235 233 goto out_err; 236 234 237 - err = create_lockd_family(serv, net, PF_INET6); 235 + err = create_lockd_family(serv, net, PF_INET6, cred); 238 236 if (err < 0 && err != -EAFNOSUPPORT) 239 237 goto out_err; 240 238 ··· 250 246 return err; 251 247 } 252 248 253 - static int lockd_up_net(struct svc_serv *serv, struct net *net) 249 + static int lockd_up_net(struct svc_serv *serv, struct net *net, 250 + const struct cred *cred) 254 251 { 255 252 struct lockd_net *ln = net_generic(net, lockd_net_id); 256 253 int error; ··· 263 258 if (error) 264 259 goto err_bind; 265 260 266 - error = make_socks(serv, net); 261 + error = make_socks(serv, net, cred); 267 262 if (error < 0) 268 263 goto err_bind; 269 264 set_grace_period(net); ··· 466 461 /* 467 462 * Bring up the lockd process if it's not already up. 468 463 */ 469 - int lockd_up(struct net *net) 464 + int lockd_up(struct net *net, const struct cred *cred) 470 465 { 471 466 struct svc_serv *serv; 472 467 int error; ··· 479 474 goto err_create; 480 475 } 481 476 482 - error = lockd_up_net(serv, net); 477 + error = lockd_up_net(serv, net, cred); 483 478 if (error < 0) { 484 479 lockd_unregister_notifiers(); 485 480 goto err_put; ··· 812 807 .pg_name = "lockd", /* service name */ 813 808 .pg_class = "nfsd", /* share authentication with nfsd */ 814 809 .pg_stats = &nlmsvc_stats, /* stats table */ 815 - .pg_authenticate = &lockd_authenticate /* export authentication */ 810 + .pg_authenticate = &lockd_authenticate, /* export authentication */ 811 + .pg_init_request = svc_generic_init_request, 812 + .pg_rpcbind_set = svc_generic_rpcbind_set, 816 813 };
+6 -6
fs/locks.c
··· 352 352 353 353 void locks_release_private(struct file_lock *fl) 354 354 { 355 + BUG_ON(waitqueue_active(&fl->fl_wait)); 356 + BUG_ON(!list_empty(&fl->fl_list)); 357 + BUG_ON(!list_empty(&fl->fl_blocked_requests)); 358 + BUG_ON(!list_empty(&fl->fl_blocked_member)); 359 + BUG_ON(!hlist_unhashed(&fl->fl_link)); 360 + 355 361 if (fl->fl_ops) { 356 362 if (fl->fl_ops->fl_release_private) 357 363 fl->fl_ops->fl_release_private(fl); ··· 377 371 /* Free a lock which is not in use. */ 378 372 void locks_free_lock(struct file_lock *fl) 379 373 { 380 - BUG_ON(waitqueue_active(&fl->fl_wait)); 381 - BUG_ON(!list_empty(&fl->fl_list)); 382 - BUG_ON(!list_empty(&fl->fl_blocked_requests)); 383 - BUG_ON(!list_empty(&fl->fl_blocked_member)); 384 - BUG_ON(!hlist_unhashed(&fl->fl_link)); 385 - 386 374 locks_release_private(fl); 387 375 kmem_cache_free(filelock_cache, fl); 388 376 }
+7 -2
fs/nfs/callback.c
··· 41 41 42 42 static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net) 43 43 { 44 + const struct cred *cred = current_cred(); 44 45 int ret; 45 46 struct nfs_net *nn = net_generic(net, nfs_net_id); 46 47 47 48 ret = svc_create_xprt(serv, "tcp", net, PF_INET, 48 - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); 49 + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS, 50 + cred); 49 51 if (ret <= 0) 50 52 goto out_err; 51 53 nn->nfs_callback_tcpport = ret; ··· 55 53 nn->nfs_callback_tcpport, PF_INET, net->ns.inum); 56 54 57 55 ret = svc_create_xprt(serv, "tcp", net, PF_INET6, 58 - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); 56 + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS, 57 + cred); 59 58 if (ret > 0) { 60 59 nn->nfs_callback_tcpport6 = ret; 61 60 dprintk("NFS: Callback listener port = %u (af %u, net %x)\n", ··· 460 457 .pg_class = "nfs", /* authentication class */ 461 458 .pg_stats = &nfs4_callback_stats, 462 459 .pg_authenticate = nfs_callback_authenticate, 460 + .pg_init_request = svc_generic_init_request, 461 + .pg_rpcbind_set = svc_generic_rpcbind_set, 463 462 };
+1 -1
fs/nfs/callback_xdr.c
··· 983 983 984 984 out_invalidcred: 985 985 pr_warn_ratelimited("NFS: NFSv4 callback contains invalid cred\n"); 986 - return rpc_autherr_badcred; 986 + return svc_return_autherr(rqstp, rpc_autherr_badcred); 987 987 } 988 988 989 989 /*
+1
fs/nfs/client.c
··· 558 558 1 : 0, 559 559 .net = clp->cl_net, 560 560 .nlmclnt_ops = clp->cl_nfs_mod->rpc_ops->nlmclnt_ops, 561 + .cred = current_cred(), 561 562 }; 562 563 563 564 if (nlm_init.nfs_version > 3)
+10 -8
fs/nfsd/export.c
··· 570 570 err = get_int(&mesg, &an_int); 571 571 if (err) 572 572 goto out3; 573 - exp.ex_anon_uid= make_kuid(&init_user_ns, an_int); 573 + exp.ex_anon_uid= make_kuid(current_user_ns(), an_int); 574 574 575 575 /* anon gid */ 576 576 err = get_int(&mesg, &an_int); 577 577 if (err) 578 578 goto out3; 579 - exp.ex_anon_gid= make_kgid(&init_user_ns, an_int); 579 + exp.ex_anon_gid= make_kgid(current_user_ns(), an_int); 580 580 581 581 /* fsid */ 582 582 err = get_int(&mesg, &an_int); ··· 1170 1170 static void exp_flags(struct seq_file *m, int flag, int fsid, 1171 1171 kuid_t anonu, kgid_t anong, struct nfsd4_fs_locations *fsloc) 1172 1172 { 1173 + struct user_namespace *userns = m->file->f_cred->user_ns; 1174 + 1173 1175 show_expflags(m, flag, NFSEXP_ALLFLAGS); 1174 1176 if (flag & NFSEXP_FSID) 1175 1177 seq_printf(m, ",fsid=%d", fsid); 1176 - if (!uid_eq(anonu, make_kuid(&init_user_ns, (uid_t)-2)) && 1177 - !uid_eq(anonu, make_kuid(&init_user_ns, 0x10000-2))) 1178 - seq_printf(m, ",anonuid=%u", from_kuid(&init_user_ns, anonu)); 1179 - if (!gid_eq(anong, make_kgid(&init_user_ns, (gid_t)-2)) && 1180 - !gid_eq(anong, make_kgid(&init_user_ns, 0x10000-2))) 1181 - seq_printf(m, ",anongid=%u", from_kgid(&init_user_ns, anong)); 1178 + if (!uid_eq(anonu, make_kuid(userns, (uid_t)-2)) && 1179 + !uid_eq(anonu, make_kuid(userns, 0x10000-2))) 1180 + seq_printf(m, ",anonuid=%u", from_kuid_munged(userns, anonu)); 1181 + if (!gid_eq(anong, make_kgid(userns, (gid_t)-2)) && 1182 + !gid_eq(anong, make_kgid(userns, 0x10000-2))) 1183 + seq_printf(m, ",anongid=%u", from_kgid_munged(userns, anong)); 1182 1184 if (fsloc && fsloc->locations_count > 0) { 1183 1185 char *loctype = (fsloc->migrated) ? "refer" : "replicas"; 1184 1186 int i;
+11
fs/nfsd/netns.h
··· 104 104 time_t nfsd4_grace; 105 105 bool somebody_reclaimed; 106 106 107 + bool track_reclaim_completes; 108 + atomic_t nr_reclaim_complete; 109 + 107 110 bool nfsd_net_up; 108 111 bool lockd_up; 109 112 ··· 134 131 u32 s2s_cp_cl_id; 135 132 struct idr s2s_cp_stateids; 136 133 spinlock_t s2s_cp_lock; 134 + 135 + /* 136 + * Version information 137 + */ 138 + bool *nfsd_versions; 139 + bool *nfsd4_minorversions; 137 140 }; 138 141 139 142 /* Simple check to find out if a given net was properly initialized */ 140 143 #define nfsd_netns_ready(nn) ((nn)->sessionid_hashtbl) 144 + 145 + extern void nfsd_netns_free_versions(struct nfsd_net *nn); 141 146 142 147 extern unsigned int nfsd_net_id; 143 148 #endif /* __NFSD_NETNS_H__ */
+11 -10
fs/nfsd/nfs3xdr.c
··· 96 96 } 97 97 98 98 static __be32 * 99 - decode_sattr3(__be32 *p, struct iattr *iap) 99 + decode_sattr3(__be32 *p, struct iattr *iap, struct user_namespace *userns) 100 100 { 101 101 u32 tmp; 102 102 ··· 107 107 iap->ia_mode = ntohl(*p++); 108 108 } 109 109 if (*p++) { 110 - iap->ia_uid = make_kuid(&init_user_ns, ntohl(*p++)); 110 + iap->ia_uid = make_kuid(userns, ntohl(*p++)); 111 111 if (uid_valid(iap->ia_uid)) 112 112 iap->ia_valid |= ATTR_UID; 113 113 } 114 114 if (*p++) { 115 - iap->ia_gid = make_kgid(&init_user_ns, ntohl(*p++)); 115 + iap->ia_gid = make_kgid(userns, ntohl(*p++)); 116 116 if (gid_valid(iap->ia_gid)) 117 117 iap->ia_valid |= ATTR_GID; 118 118 } ··· 165 165 encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, 166 166 struct kstat *stat) 167 167 { 168 + struct user_namespace *userns = nfsd_user_namespace(rqstp); 168 169 struct timespec ts; 169 170 *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); 170 171 *p++ = htonl((u32) (stat->mode & S_IALLUGO)); 171 172 *p++ = htonl((u32) stat->nlink); 172 - *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); 173 - *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); 173 + *p++ = htonl((u32) from_kuid_munged(userns, stat->uid)); 174 + *p++ = htonl((u32) from_kgid_munged(userns, stat->gid)); 174 175 if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) { 175 176 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN); 176 177 } else { ··· 326 325 p = decode_fh(p, &args->fh); 327 326 if (!p) 328 327 return 0; 329 - p = decode_sattr3(p, &args->attrs); 328 + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); 330 329 331 330 if ((args->check_guard = ntohl(*p++)) != 0) { 332 331 struct timespec time; ··· 456 455 switch (args->createmode = ntohl(*p++)) { 457 456 case NFS3_CREATE_UNCHECKED: 458 457 case NFS3_CREATE_GUARDED: 459 - p = decode_sattr3(p, &args->attrs); 458 + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); 460 459 break; 461 460 case NFS3_CREATE_EXCLUSIVE: 462 461 args->verf = p; ··· 477 476 if (!(p = decode_fh(p, &args->fh)) || 478 477 !(p = decode_filename(p, &args->name, &args->len))) 479 478 return 0; 480 - p = decode_sattr3(p, &args->attrs); 479 + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); 481 480 482 481 return xdr_argsize_check(rqstp, p); 483 482 } ··· 492 491 if (!(p = decode_fh(p, &args->ffh)) || 493 492 !(p = decode_filename(p, &args->fname, &args->flen))) 494 493 return 0; 495 - p = decode_sattr3(p, &args->attrs); 494 + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); 496 495 497 496 args->tlen = ntohl(*p++); 498 497 ··· 520 519 521 520 if (args->ftype == NF3BLK || args->ftype == NF3CHR 522 521 || args->ftype == NF3SOCK || args->ftype == NF3FIFO) 523 - p = decode_sattr3(p, &args->attrs); 522 + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); 524 523 525 524 if (args->ftype == NF3BLK || args->ftype == NF3CHR) { 526 525 args->major = ntohl(*p++);
+5 -4
fs/nfsd/nfs4callback.c
··· 1123 1123 rpc_restart_call_prepare(task); 1124 1124 return; 1125 1125 case 1: 1126 - break; 1127 - case -1: 1128 - /* Network partition? */ 1129 - nfsd4_mark_cb_down(clp, task->tk_status); 1126 + switch (task->tk_status) { 1127 + case -EIO: 1128 + case -ETIMEDOUT: 1129 + nfsd4_mark_cb_down(clp, task->tk_status); 1130 + } 1130 1131 break; 1131 1132 default: 1132 1133 BUG();
+4 -4
fs/nfsd/nfs4idmap.c
··· 634 634 return nfserr_inval; 635 635 636 636 status = do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, &id); 637 - *uid = make_kuid(&init_user_ns, id); 637 + *uid = make_kuid(nfsd_user_namespace(rqstp), id); 638 638 if (!uid_valid(*uid)) 639 639 status = nfserr_badowner; 640 640 return status; ··· 651 651 return nfserr_inval; 652 652 653 653 status = do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, &id); 654 - *gid = make_kgid(&init_user_ns, id); 654 + *gid = make_kgid(nfsd_user_namespace(rqstp), id); 655 655 if (!gid_valid(*gid)) 656 656 status = nfserr_badowner; 657 657 return status; ··· 660 660 __be32 nfsd4_encode_user(struct xdr_stream *xdr, struct svc_rqst *rqstp, 661 661 kuid_t uid) 662 662 { 663 - u32 id = from_kuid(&init_user_ns, uid); 663 + u32 id = from_kuid_munged(nfsd_user_namespace(rqstp), uid); 664 664 return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_USER, id); 665 665 } 666 666 667 667 __be32 nfsd4_encode_group(struct xdr_stream *xdr, struct svc_rqst *rqstp, 668 668 kgid_t gid) 669 669 { 670 - u32 id = from_kgid(&init_user_ns, gid); 670 + u32 id = from_kgid_munged(nfsd_user_namespace(rqstp), gid); 671 671 return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_GROUP, id); 672 672 }
+1 -1
fs/nfsd/nfs4layouts.c
··· 693 693 ops->fence_client(ls); 694 694 else 695 695 nfsd4_cb_layout_fail(ls); 696 - return -1; 696 + return 1; 697 697 case -NFS4ERR_NOMATCHING_LAYOUT: 698 698 trace_nfsd_layout_recall_done(&ls->ls_stid.sc_stateid); 699 699 task->tk_status = 0;
+2 -1
fs/nfsd/nfs4proc.c
··· 1927 1927 struct nfsd4_compound_state *cstate = &resp->cstate; 1928 1928 struct svc_fh *current_fh = &cstate->current_fh; 1929 1929 struct svc_fh *save_fh = &cstate->save_fh; 1930 + struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 1930 1931 __be32 status; 1931 1932 1932 1933 svcxdr_init_encode(rqstp, resp); ··· 1950 1949 * According to RFC3010, this takes precedence over all other errors. 1951 1950 */ 1952 1951 status = nfserr_minor_vers_mismatch; 1953 - if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0) 1952 + if (nfsd_minorversion(nn, args->minorversion, NFSD_TEST) <= 0) 1954 1953 goto out; 1955 1954 status = nfserr_resource; 1956 1955 if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
+401 -35
fs/nfsd/nfs4recover.c
··· 169 169 } 170 170 171 171 static void 172 + __nfsd4_create_reclaim_record_grace(struct nfs4_client *clp, 173 + const char *dname, int len, struct nfsd_net *nn) 174 + { 175 + struct xdr_netobj name; 176 + struct nfs4_client_reclaim *crp; 177 + 178 + name.data = kmemdup(dname, len, GFP_KERNEL); 179 + if (!name.data) { 180 + dprintk("%s: failed to allocate memory for name.data!\n", 181 + __func__); 182 + return; 183 + } 184 + name.len = len; 185 + crp = nfs4_client_to_reclaim(name, nn); 186 + if (!crp) { 187 + kfree(name.data); 188 + return; 189 + } 190 + crp->cr_clp = clp; 191 + } 192 + 193 + static void 172 194 nfsd4_create_clid_dir(struct nfs4_client *clp) 173 195 { 174 196 const struct cred *original_cred; 175 197 char dname[HEXDIR_LEN]; 176 198 struct dentry *dir, *dentry; 177 - struct nfs4_client_reclaim *crp; 178 199 int status; 179 200 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 180 201 ··· 241 220 out_unlock: 242 221 inode_unlock(d_inode(dir)); 243 222 if (status == 0) { 244 - if (nn->in_grace) { 245 - crp = nfs4_client_to_reclaim(dname, nn); 246 - if (crp) 247 - crp->cr_clp = clp; 248 - } 223 + if (nn->in_grace) 224 + __nfsd4_create_reclaim_record_grace(clp, dname, 225 + HEXDIR_LEN, nn); 249 226 vfs_fsync(nn->rec_file, 0); 250 227 } else { 251 228 printk(KERN_ERR "NFSD: failed to write recovery record" ··· 364 345 } 365 346 366 347 static void 348 + __nfsd4_remove_reclaim_record_grace(const char *dname, int len, 349 + struct nfsd_net *nn) 350 + { 351 + struct xdr_netobj name; 352 + struct nfs4_client_reclaim *crp; 353 + 354 + name.data = kmemdup(dname, len, GFP_KERNEL); 355 + if (!name.data) { 356 + dprintk("%s: failed to allocate memory for name.data!\n", 357 + __func__); 358 + return; 359 + } 360 + name.len = len; 361 + crp = nfsd4_find_reclaim_client(name, nn); 362 + kfree(name.data); 363 + if (crp) 364 + nfs4_remove_reclaim_record(crp, nn); 365 + } 366 + 367 + static void 367 368 nfsd4_remove_clid_dir(struct nfs4_client *clp) 368 369 { 369 370 const struct cred *original_cred; 370 - struct nfs4_client_reclaim *crp; 371 371 char dname[HEXDIR_LEN]; 372 372 int status; 373 373 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); ··· 411 373 nfs4_reset_creds(original_cred); 412 374 if (status == 0) { 413 375 vfs_fsync(nn->rec_file, 0); 414 - if (nn->in_grace) { 415 - /* remove reclaim record */ 416 - crp = nfsd4_find_reclaim_client(dname, nn); 417 - if (crp) 418 - nfs4_remove_reclaim_record(crp, nn); 419 - } 376 + if (nn->in_grace) 377 + __nfsd4_remove_reclaim_record_grace(dname, 378 + HEXDIR_LEN, nn); 420 379 } 421 380 out_drop_write: 422 381 mnt_drop_write_file(nn->rec_file); ··· 427 392 purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn) 428 393 { 429 394 int status; 395 + struct xdr_netobj name; 430 396 431 - if (nfs4_has_reclaimed_state(child->d_name.name, nn)) 397 + if (child->d_name.len != HEXDIR_LEN - 1) { 398 + printk("%s: illegal name %pd in recovery directory\n", 399 + __func__, child); 400 + /* Keep trying; maybe the others are OK: */ 432 401 return 0; 402 + } 403 + name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL); 404 + if (!name.data) { 405 + dprintk("%s: failed to allocate memory for name.data!\n", 406 + __func__); 407 + goto out; 408 + } 409 + name.len = HEXDIR_LEN; 410 + if (nfs4_has_reclaimed_state(name, nn)) 411 + goto out_free; 433 412 434 413 status = vfs_rmdir(d_inode(parent), child); 435 414 if (status) 436 415 printk("failed to remove client recovery directory %pd\n", 437 416 child); 417 + out_free: 418 + kfree(name.data); 419 + out: 438 420 /* Keep trying, success or failure: */ 439 421 return 0; 440 422 } ··· 481 429 static int 482 430 load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn) 483 431 { 432 + struct xdr_netobj name; 433 + 484 434 if (child->d_name.len != HEXDIR_LEN - 1) { 485 - printk("nfsd4: illegal name %pd in recovery directory\n", 486 - child); 435 + printk("%s: illegal name %pd in recovery directory\n", 436 + __func__, child); 487 437 /* Keep trying; maybe the others are OK: */ 488 438 return 0; 489 439 } 490 - nfs4_client_to_reclaim(child->d_name.name, nn); 440 + name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL); 441 + if (!name.data) { 442 + dprintk("%s: failed to allocate memory for name.data!\n", 443 + __func__); 444 + goto out; 445 + } 446 + name.len = HEXDIR_LEN; 447 + if (!nfs4_client_to_reclaim(name, nn)) 448 + kfree(name.data); 449 + out: 491 450 return 0; 492 451 } 493 452 ··· 627 564 status = nfsd4_load_reboot_recovery_data(net); 628 565 if (status) 629 566 goto err; 567 + printk("NFSD: Using legacy client tracking operations.\n"); 630 568 return 0; 631 569 632 570 err: ··· 679 615 char dname[HEXDIR_LEN]; 680 616 struct nfs4_client_reclaim *crp; 681 617 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 618 + struct xdr_netobj name; 682 619 683 620 /* did we already find that this client is stable? */ 684 621 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) ··· 692 627 } 693 628 694 629 /* look for it in the reclaim hashtable otherwise */ 695 - crp = nfsd4_find_reclaim_client(dname, nn); 630 + name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL); 631 + if (!name.data) { 632 + dprintk("%s: failed to allocate memory for name.data!\n", 633 + __func__); 634 + goto out_enoent; 635 + } 636 + name.len = HEXDIR_LEN; 637 + crp = nfsd4_find_reclaim_client(name, nn); 638 + kfree(name.data); 696 639 if (crp) { 697 640 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 698 641 crp->cr_clp = clp; 699 642 return 0; 700 643 } 701 644 645 + out_enoent: 702 646 return -ENOENT; 703 647 } 704 648 ··· 730 656 spinlock_t cn_lock; 731 657 struct list_head cn_list; 732 658 unsigned int cn_xid; 659 + bool cn_has_legacy; 733 660 }; 734 661 735 662 struct cld_upcall { ··· 781 706 } 782 707 783 708 static ssize_t 709 + __cld_pipe_inprogress_downcall(const struct cld_msg __user *cmsg, 710 + struct nfsd_net *nn) 711 + { 712 + uint8_t cmd; 713 + struct xdr_netobj name; 714 + uint16_t namelen; 715 + struct cld_net *cn = nn->cld_net; 716 + 717 + if (get_user(cmd, &cmsg->cm_cmd)) { 718 + dprintk("%s: error when copying cmd from userspace", __func__); 719 + return -EFAULT; 720 + } 721 + if (cmd == Cld_GraceStart) { 722 + if (get_user(namelen, &cmsg->cm_u.cm_name.cn_len)) 723 + return -EFAULT; 724 + name.data = memdup_user(&cmsg->cm_u.cm_name.cn_id, namelen); 725 + if (IS_ERR_OR_NULL(name.data)) 726 + return -EFAULT; 727 + name.len = namelen; 728 + if (name.len > 5 && memcmp(name.data, "hash:", 5) == 0) { 729 + name.len = name.len - 5; 730 + memmove(name.data, name.data + 5, name.len); 731 + cn->cn_has_legacy = true; 732 + } 733 + if (!nfs4_client_to_reclaim(name, nn)) { 734 + kfree(name.data); 735 + return -EFAULT; 736 + } 737 + return sizeof(*cmsg); 738 + } 739 + return -EFAULT; 740 + } 741 + 742 + static ssize_t 784 743 cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) 785 744 { 786 745 struct cld_upcall *tmp, *cup; ··· 823 714 struct nfsd_net *nn = net_generic(file_inode(filp)->i_sb->s_fs_info, 824 715 nfsd_net_id); 825 716 struct cld_net *cn = nn->cld_net; 717 + int16_t status; 826 718 827 719 if (mlen != sizeof(*cmsg)) { 828 720 dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen, ··· 837 727 return -EFAULT; 838 728 } 839 729 730 + /* 731 + * copy the status so we know whether to remove the upcall from the 732 + * list (for -EINPROGRESS, we just want to make sure the xid is 733 + * valid, not remove the upcall from the list) 734 + */ 735 + if (get_user(status, &cmsg->cm_status)) { 736 + dprintk("%s: error when copying status from userspace", __func__); 737 + return -EFAULT; 738 + } 739 + 840 740 /* walk the list and find corresponding xid */ 841 741 cup = NULL; 842 742 spin_lock(&cn->cn_lock); 843 743 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 844 744 if (get_unaligned(&tmp->cu_msg.cm_xid) == xid) { 845 745 cup = tmp; 846 - list_del_init(&cup->cu_list); 746 + if (status != -EINPROGRESS) 747 + list_del_init(&cup->cu_list); 847 748 break; 848 749 } 849 750 } ··· 865 744 dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid); 866 745 return -EINVAL; 867 746 } 747 + 748 + if (status == -EINPROGRESS) 749 + return __cld_pipe_inprogress_downcall(cmsg, nn); 868 750 869 751 if (copy_from_user(&cup->cu_msg, src, mlen) != 0) 870 752 return -EFAULT; ··· 944 820 945 821 /* Initialize rpc_pipefs pipe for communication with client tracking daemon */ 946 822 static int 947 - nfsd4_init_cld_pipe(struct net *net) 823 + __nfsd4_init_cld_pipe(struct net *net) 948 824 { 949 825 int ret; 950 826 struct dentry *dentry; ··· 975 851 } 976 852 977 853 cn->cn_pipe->dentry = dentry; 854 + cn->cn_has_legacy = false; 978 855 nn->cld_net = cn; 979 856 return 0; 980 857 ··· 986 861 printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n", 987 862 ret); 988 863 return ret; 864 + } 865 + 866 + static int 867 + nfsd4_init_cld_pipe(struct net *net) 868 + { 869 + int status; 870 + 871 + status = __nfsd4_init_cld_pipe(net); 872 + if (!status) 873 + printk("NFSD: Using old nfsdcld client tracking operations.\n"); 874 + return status; 989 875 } 990 876 991 877 static void ··· 1127 991 "record from stable storage: %d\n", ret); 1128 992 } 1129 993 1130 - /* Check for presence of a record, and update its timestamp */ 994 + /* 995 + * For older nfsdcld's that do not allow us to "slurp" the clients 996 + * from the tracking database during startup. 997 + * 998 + * Check for presence of a record, and update its timestamp 999 + */ 1131 1000 static int 1132 - nfsd4_cld_check(struct nfs4_client *clp) 1001 + nfsd4_cld_check_v0(struct nfs4_client *clp) 1133 1002 { 1134 1003 int ret; 1135 1004 struct cld_upcall *cup; ··· 1167 1026 return ret; 1168 1027 } 1169 1028 1029 + /* 1030 + * For newer nfsdcld's that allow us to "slurp" the clients 1031 + * from the tracking database during startup. 1032 + * 1033 + * Check for presence of a record in the reclaim_str_hashtbl 1034 + */ 1035 + static int 1036 + nfsd4_cld_check(struct nfs4_client *clp) 1037 + { 1038 + struct nfs4_client_reclaim *crp; 1039 + struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1040 + struct cld_net *cn = nn->cld_net; 1041 + int status; 1042 + char dname[HEXDIR_LEN]; 1043 + struct xdr_netobj name; 1044 + 1045 + /* did we already find that this client is stable? */ 1046 + if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1047 + return 0; 1048 + 1049 + /* look for it in the reclaim hashtable otherwise */ 1050 + crp = nfsd4_find_reclaim_client(clp->cl_name, nn); 1051 + if (crp) 1052 + goto found; 1053 + 1054 + if (cn->cn_has_legacy) { 1055 + status = nfs4_make_rec_clidname(dname, &clp->cl_name); 1056 + if (status) 1057 + return -ENOENT; 1058 + 1059 + name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL); 1060 + if (!name.data) { 1061 + dprintk("%s: failed to allocate memory for name.data!\n", 1062 + __func__); 1063 + return -ENOENT; 1064 + } 1065 + name.len = HEXDIR_LEN; 1066 + crp = nfsd4_find_reclaim_client(name, nn); 1067 + kfree(name.data); 1068 + if (crp) 1069 + goto found; 1070 + 1071 + } 1072 + return -ENOENT; 1073 + found: 1074 + crp->cr_clp = clp; 1075 + return 0; 1076 + } 1077 + 1078 + static int 1079 + nfsd4_cld_grace_start(struct nfsd_net *nn) 1080 + { 1081 + int ret; 1082 + struct cld_upcall *cup; 1083 + struct cld_net *cn = nn->cld_net; 1084 + 1085 + cup = alloc_cld_upcall(cn); 1086 + if (!cup) { 1087 + ret = -ENOMEM; 1088 + goto out_err; 1089 + } 1090 + 1091 + cup->cu_msg.cm_cmd = Cld_GraceStart; 1092 + ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 1093 + if (!ret) 1094 + ret = cup->cu_msg.cm_status; 1095 + 1096 + free_cld_upcall(cup); 1097 + out_err: 1098 + if (ret) 1099 + dprintk("%s: Unable to get clients from userspace: %d\n", 1100 + __func__, ret); 1101 + return ret; 1102 + } 1103 + 1104 + /* For older nfsdcld's that need cm_gracetime */ 1170 1105 static void 1171 - nfsd4_cld_grace_done(struct nfsd_net *nn) 1106 + nfsd4_cld_grace_done_v0(struct nfsd_net *nn) 1172 1107 { 1173 1108 int ret; 1174 1109 struct cld_upcall *cup; ··· 1268 1051 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); 1269 1052 } 1270 1053 1271 - static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { 1054 + /* 1055 + * For newer nfsdcld's that do not need cm_gracetime. We also need to call 1056 + * nfs4_release_reclaim() to clear out the reclaim_str_hashtbl. 1057 + */ 1058 + static void 1059 + nfsd4_cld_grace_done(struct nfsd_net *nn) 1060 + { 1061 + int ret; 1062 + struct cld_upcall *cup; 1063 + struct cld_net *cn = nn->cld_net; 1064 + 1065 + cup = alloc_cld_upcall(cn); 1066 + if (!cup) { 1067 + ret = -ENOMEM; 1068 + goto out_err; 1069 + } 1070 + 1071 + cup->cu_msg.cm_cmd = Cld_GraceDone; 1072 + ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 1073 + if (!ret) 1074 + ret = cup->cu_msg.cm_status; 1075 + 1076 + free_cld_upcall(cup); 1077 + out_err: 1078 + nfs4_release_reclaim(nn); 1079 + if (ret) 1080 + printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); 1081 + } 1082 + 1083 + static int 1084 + nfs4_cld_state_init(struct net *net) 1085 + { 1086 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1087 + int i; 1088 + 1089 + nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE, 1090 + sizeof(struct list_head), 1091 + GFP_KERNEL); 1092 + if (!nn->reclaim_str_hashtbl) 1093 + return -ENOMEM; 1094 + 1095 + for (i = 0; i < CLIENT_HASH_SIZE; i++) 1096 + INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]); 1097 + nn->reclaim_str_hashtbl_size = 0; 1098 + nn->track_reclaim_completes = true; 1099 + atomic_set(&nn->nr_reclaim_complete, 0); 1100 + 1101 + return 0; 1102 + } 1103 + 1104 + static void 1105 + nfs4_cld_state_shutdown(struct net *net) 1106 + { 1107 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1108 + 1109 + nn->track_reclaim_completes = false; 1110 + kfree(nn->reclaim_str_hashtbl); 1111 + } 1112 + 1113 + static bool 1114 + cld_running(struct nfsd_net *nn) 1115 + { 1116 + struct cld_net *cn = nn->cld_net; 1117 + struct rpc_pipe *pipe = cn->cn_pipe; 1118 + 1119 + return pipe->nreaders || pipe->nwriters; 1120 + } 1121 + 1122 + static int 1123 + nfsd4_cld_tracking_init(struct net *net) 1124 + { 1125 + int status; 1126 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1127 + bool running; 1128 + int retries = 10; 1129 + 1130 + status = nfs4_cld_state_init(net); 1131 + if (status) 1132 + return status; 1133 + 1134 + status = __nfsd4_init_cld_pipe(net); 1135 + if (status) 1136 + goto err_shutdown; 1137 + 1138 + /* 1139 + * rpc pipe upcalls take 30 seconds to time out, so we don't want to 1140 + * queue an upcall unless we know that nfsdcld is running (because we 1141 + * want this to fail fast so that nfsd4_client_tracking_init() can try 1142 + * the next client tracking method). nfsdcld should already be running 1143 + * before nfsd is started, so the wait here is for nfsdcld to open the 1144 + * pipefs file we just created. 1145 + */ 1146 + while (!(running = cld_running(nn)) && retries--) 1147 + msleep(100); 1148 + 1149 + if (!running) { 1150 + status = -ETIMEDOUT; 1151 + goto err_remove; 1152 + } 1153 + 1154 + status = nfsd4_cld_grace_start(nn); 1155 + if (status) { 1156 + if (status == -EOPNOTSUPP) 1157 + printk(KERN_WARNING "NFSD: Please upgrade nfsdcld.\n"); 1158 + nfs4_release_reclaim(nn); 1159 + goto err_remove; 1160 + } else 1161 + printk("NFSD: Using nfsdcld client tracking operations.\n"); 1162 + return 0; 1163 + 1164 + err_remove: 1165 + nfsd4_remove_cld_pipe(net); 1166 + err_shutdown: 1167 + nfs4_cld_state_shutdown(net); 1168 + return status; 1169 + } 1170 + 1171 + static void 1172 + nfsd4_cld_tracking_exit(struct net *net) 1173 + { 1174 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1175 + 1176 + nfs4_release_reclaim(nn); 1177 + nfsd4_remove_cld_pipe(net); 1178 + nfs4_cld_state_shutdown(net); 1179 + } 1180 + 1181 + /* For older nfsdcld's */ 1182 + static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v0 = { 1272 1183 .init = nfsd4_init_cld_pipe, 1273 1184 .exit = nfsd4_remove_cld_pipe, 1185 + .create = nfsd4_cld_create, 1186 + .remove = nfsd4_cld_remove, 1187 + .check = nfsd4_cld_check_v0, 1188 + .grace_done = nfsd4_cld_grace_done_v0, 1189 + }; 1190 + 1191 + /* For newer nfsdcld's */ 1192 + static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { 1193 + .init = nfsd4_cld_tracking_init, 1194 + .exit = nfsd4_cld_tracking_exit, 1274 1195 .create = nfsd4_cld_create, 1275 1196 .remove = nfsd4_cld_remove, 1276 1197 .check = nfsd4_cld_check, ··· 1622 1267 1623 1268 ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL); 1624 1269 kfree(grace_start); 1270 + if (!ret) 1271 + printk("NFSD: Using UMH upcall client tracking operations.\n"); 1625 1272 return ret; 1626 1273 } 1627 1274 ··· 1773 1416 if (nn->client_tracking_ops) 1774 1417 goto do_init; 1775 1418 1419 + /* First, try to use nfsdcld */ 1420 + nn->client_tracking_ops = &nfsd4_cld_tracking_ops; 1421 + status = nn->client_tracking_ops->init(net); 1422 + if (!status) 1423 + return status; 1424 + if (status != -ETIMEDOUT) { 1425 + nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v0; 1426 + status = nn->client_tracking_ops->init(net); 1427 + if (!status) 1428 + return status; 1429 + } 1430 + 1776 1431 /* 1777 - * First, try a UMH upcall. It should succeed or fail quickly, so 1778 - * there's little harm in trying that first. 1432 + * Next, try the UMH upcall. 1779 1433 */ 1780 1434 nn->client_tracking_ops = &nfsd4_umh_tracking_ops; 1781 1435 status = nn->client_tracking_ops->init(net); ··· 1794 1426 return status; 1795 1427 1796 1428 /* 1797 - * See if the recoverydir exists and is a directory. If it is, 1798 - * then use the legacy ops. 1429 + * Finally, See if the recoverydir exists and is a directory. 1430 + * If it is, then use the legacy ops. 1799 1431 */ 1800 1432 nn->client_tracking_ops = &nfsd4_legacy_tracking_ops; 1801 1433 status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path); 1802 1434 if (!status) { 1803 1435 status = d_is_dir(path.dentry); 1804 1436 path_put(&path); 1805 - if (status) 1806 - goto do_init; 1437 + if (!status) { 1438 + status = -EINVAL; 1439 + goto out; 1440 + } 1807 1441 } 1808 1442 1809 - /* Finally, try to use nfsdcld */ 1810 - nn->client_tracking_ops = &nfsd4_cld_tracking_ops; 1811 - printk(KERN_WARNING "NFSD: the nfsdcld client tracking upcall will be " 1812 - "removed in 3.10. Please transition to using " 1813 - "nfsdcltrack.\n"); 1814 1443 do_init: 1815 1444 status = nn->client_tracking_ops->init(net); 1445 + out: 1816 1446 if (status) { 1817 1447 printk(KERN_WARNING "NFSD: Unable to initialize client " 1818 1448 "recovery tracking! (%d)\n", status);
+51 -17
fs/nfsd/nfs4state.c
··· 77 77 /* forward declarations */ 78 78 static bool check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner); 79 79 static void nfs4_free_ol_stateid(struct nfs4_stid *stid); 80 + void nfsd4_end_grace(struct nfsd_net *nn); 80 81 81 82 /* Locking: */ 82 83 ··· 1068 1067 return id & CLIENT_HASH_MASK; 1069 1068 } 1070 1069 1071 - static unsigned int clientstr_hashval(const char *name) 1070 + static unsigned int clientstr_hashval(struct xdr_netobj name) 1072 1071 { 1073 - return opaque_hashval(name, 8) & CLIENT_HASH_MASK; 1072 + return opaque_hashval(name.data, 8) & CLIENT_HASH_MASK; 1074 1073 } 1075 1074 1076 1075 /* ··· 1998 1997 __destroy_client(clp); 1999 1998 } 2000 1999 2000 + static void inc_reclaim_complete(struct nfs4_client *clp) 2001 + { 2002 + struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 2003 + 2004 + if (!nn->track_reclaim_completes) 2005 + return; 2006 + if (!nfsd4_find_reclaim_client(clp->cl_name, nn)) 2007 + return; 2008 + if (atomic_inc_return(&nn->nr_reclaim_complete) == 2009 + nn->reclaim_str_hashtbl_size) { 2010 + printk(KERN_INFO "NFSD: all clients done reclaiming, ending NFSv4 grace period (net %x)\n", 2011 + clp->net->ns.inum); 2012 + nfsd4_end_grace(nn); 2013 + } 2014 + } 2015 + 2001 2016 static void expire_client(struct nfs4_client *clp) 2002 2017 { 2003 2018 unhash_client(clp); ··· 2063 2046 if (o1->len > o2->len) 2064 2047 return 1; 2065 2048 return memcmp(o1->data, o2->data, o1->len); 2066 - } 2067 - 2068 - static int same_name(const char *n1, const char *n2) 2069 - { 2070 - return 0 == memcmp(n1, n2, HEXDIR_LEN); 2071 2049 } 2072 2050 2073 2051 static int ··· 3366 3354 3367 3355 status = nfs_ok; 3368 3356 nfsd4_client_record_create(cstate->session->se_client); 3357 + inc_reclaim_complete(cstate->session->se_client); 3369 3358 out: 3370 3359 return status; 3371 3360 } ··· 3971 3958 switch (task->tk_status) { 3972 3959 case 0: 3973 3960 return 1; 3961 + case -NFS4ERR_DELAY: 3962 + rpc_delay(task, 2 * HZ); 3963 + return 0; 3974 3964 case -EBADHANDLE: 3975 3965 case -NFS4ERR_BAD_STATEID: 3976 3966 /* ··· 3986 3970 } 3987 3971 /*FALLTHRU*/ 3988 3972 default: 3989 - return -1; 3973 + return 1; 3990 3974 } 3991 3975 } 3992 3976 ··· 4729 4713 if (nn->grace_ended) 4730 4714 return; 4731 4715 4732 - dprintk("NFSD: end of grace period\n"); 4733 4716 nn->grace_ended = true; 4734 4717 /* 4735 4718 * If the server goes down again right now, an NFSv4 ··· 4764 4749 unsigned long double_grace_period_end = nn->boot_time + 4765 4750 2 * nn->nfsd4_lease; 4766 4751 4752 + if (nn->track_reclaim_completes && 4753 + atomic_read(&nn->nr_reclaim_complete) == 4754 + nn->reclaim_str_hashtbl_size) 4755 + return false; 4767 4756 if (!nn->somebody_reclaimed) 4768 4757 return false; 4769 4758 nn->somebody_reclaimed = false; ··· 4798 4779 new_timeo = 0; 4799 4780 goto out; 4800 4781 } 4782 + dprintk("NFSD: end of grace period\n"); 4801 4783 nfsd4_end_grace(nn); 4802 4784 INIT_LIST_HEAD(&reaplist); 4803 4785 spin_lock(&nn->client_lock); ··· 6478 6458 } 6479 6459 6480 6460 bool 6481 - nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn) 6461 + nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn) 6482 6462 { 6483 6463 struct nfs4_client_reclaim *crp; 6484 6464 ··· 6488 6468 6489 6469 /* 6490 6470 * failure => all reset bets are off, nfserr_no_grace... 6471 + * 6472 + * The caller is responsible for freeing name.data if NULL is returned (it 6473 + * will be freed in nfs4_remove_reclaim_record in the normal case). 6491 6474 */ 6492 6475 struct nfs4_client_reclaim * 6493 - nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn) 6476 + nfs4_client_to_reclaim(struct xdr_netobj name, struct nfsd_net *nn) 6494 6477 { 6495 6478 unsigned int strhashval; 6496 6479 struct nfs4_client_reclaim *crp; 6497 6480 6498 - dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name); 6481 + dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", name.len, name.data); 6499 6482 crp = alloc_reclaim(); 6500 6483 if (crp) { 6501 6484 strhashval = clientstr_hashval(name); 6502 6485 INIT_LIST_HEAD(&crp->cr_strhash); 6503 6486 list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]); 6504 - memcpy(crp->cr_recdir, name, HEXDIR_LEN); 6487 + crp->cr_name.data = name.data; 6488 + crp->cr_name.len = name.len; 6505 6489 crp->cr_clp = NULL; 6506 6490 nn->reclaim_str_hashtbl_size++; 6507 6491 } ··· 6516 6492 nfs4_remove_reclaim_record(struct nfs4_client_reclaim *crp, struct nfsd_net *nn) 6517 6493 { 6518 6494 list_del(&crp->cr_strhash); 6495 + kfree(crp->cr_name.data); 6519 6496 kfree(crp); 6520 6497 nn->reclaim_str_hashtbl_size--; 6521 6498 } ··· 6540 6515 /* 6541 6516 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ 6542 6517 struct nfs4_client_reclaim * 6543 - nfsd4_find_reclaim_client(const char *recdir, struct nfsd_net *nn) 6518 + nfsd4_find_reclaim_client(struct xdr_netobj name, struct nfsd_net *nn) 6544 6519 { 6545 6520 unsigned int strhashval; 6546 6521 struct nfs4_client_reclaim *crp = NULL; 6547 6522 6548 - dprintk("NFSD: nfs4_find_reclaim_client for recdir %s\n", recdir); 6523 + dprintk("NFSD: nfs4_find_reclaim_client for name %.*s\n", name.len, name.data); 6549 6524 6550 - strhashval = clientstr_hashval(recdir); 6525 + strhashval = clientstr_hashval(name); 6551 6526 list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) { 6552 - if (same_name(crp->cr_recdir, recdir)) { 6527 + if (compare_blob(&crp->cr_name, &name) == 0) { 6553 6528 return crp; 6554 6529 } 6555 6530 } ··· 7287 7262 return ret; 7288 7263 locks_start_grace(net, &nn->nfsd4_manager); 7289 7264 nfsd4_client_tracking_init(net); 7265 + if (nn->track_reclaim_completes && nn->reclaim_str_hashtbl_size == 0) 7266 + goto skip_grace; 7290 7267 printk(KERN_INFO "NFSD: starting %ld-second grace period (net %x)\n", 7291 7268 nn->nfsd4_grace, net->ns.inum); 7292 7269 queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_grace * HZ); 7270 + return 0; 7271 + 7272 + skip_grace: 7273 + printk(KERN_INFO "NFSD: no clients to reclaim, skipping NFSv4 grace period (net %x)\n", 7274 + net->ns.inum); 7275 + queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_lease * HZ); 7276 + nfsd4_end_grace(nn); 7293 7277 return 0; 7294 7278 } 7295 7279
+7 -2
fs/nfsd/nfs4xdr.c
··· 521 521 static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs) 522 522 { 523 523 DECODE_HEAD; 524 + struct user_namespace *userns = nfsd_user_namespace(argp->rqstp); 524 525 u32 dummy, uid, gid; 525 526 char *machine_name; 526 527 int i; ··· 564 563 dummy = be32_to_cpup(p++); 565 564 READ_BUF(dummy * 4); 566 565 if (cbs->flavor == (u32)(-1)) { 567 - kuid_t kuid = make_kuid(&init_user_ns, uid); 568 - kgid_t kgid = make_kgid(&init_user_ns, gid); 566 + kuid_t kuid = make_kuid(userns, uid); 567 + kgid_t kgid = make_kgid(userns, gid); 569 568 if (uid_valid(kuid) && gid_valid(kgid)) { 570 569 cbs->uid = kuid; 571 570 cbs->gid = kgid; ··· 2421 2420 __be32 status; 2422 2421 int err; 2423 2422 struct nfs4_acl *acl = NULL; 2423 + #ifdef CONFIG_NFSD_V4_SECURITY_LABEL 2424 2424 void *context = NULL; 2425 2425 int contextlen; 2426 + #endif 2426 2427 bool contextsupport = false; 2427 2428 struct nfsd4_compoundres *resp = rqstp->rq_resp; 2428 2429 u32 minorversion = resp->cstate.minorversion; ··· 2909 2906 *p++ = cpu_to_be32(NFS4_CHANGE_TYPE_IS_TIME_METADATA); 2910 2907 } 2911 2908 2909 + #ifdef CONFIG_NFSD_V4_SECURITY_LABEL 2912 2910 if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) { 2913 2911 status = nfsd4_encode_security_label(xdr, rqstp, context, 2914 2912 contextlen); 2915 2913 if (status) 2916 2914 goto out; 2917 2915 } 2916 + #endif 2918 2917 2919 2918 attrlen = htonl(xdr->buf->len - attrlen_offset - 4); 2920 2919 write_bytes_to_xdr_buf(xdr->buf, attrlen_offset, &attrlen, 4);
+23 -19
fs/nfsd/nfsctl.c
··· 439 439 return rv; 440 440 if (newthreads < 0) 441 441 return -EINVAL; 442 - rv = nfsd_svc(newthreads, net); 442 + rv = nfsd_svc(newthreads, net, file->f_cred); 443 443 if (rv < 0) 444 444 return rv; 445 445 } else ··· 537 537 } 538 538 539 539 static ssize_t 540 - nfsd_print_version_support(char *buf, int remaining, const char *sep, 541 - unsigned vers, int minor) 540 + nfsd_print_version_support(struct nfsd_net *nn, char *buf, int remaining, 541 + const char *sep, unsigned vers, int minor) 542 542 { 543 543 const char *format = minor < 0 ? "%s%c%u" : "%s%c%u.%u"; 544 - bool supported = !!nfsd_vers(vers, NFSD_TEST); 544 + bool supported = !!nfsd_vers(nn, vers, NFSD_TEST); 545 545 546 546 if (vers == 4 && minor >= 0 && 547 - !nfsd_minorversion(minor, NFSD_TEST)) 547 + !nfsd_minorversion(nn, minor, NFSD_TEST)) 548 548 supported = false; 549 549 if (minor == 0 && supported) 550 550 /* ··· 599 599 switch(num) { 600 600 case 2: 601 601 case 3: 602 - nfsd_vers(num, cmd); 602 + nfsd_vers(nn, num, cmd); 603 603 break; 604 604 case 4: 605 605 if (*minorp == '.') { 606 - if (nfsd_minorversion(minor, cmd) < 0) 606 + if (nfsd_minorversion(nn, minor, cmd) < 0) 607 607 return -EINVAL; 608 - } else if ((cmd == NFSD_SET) != nfsd_vers(num, NFSD_TEST)) { 608 + } else if ((cmd == NFSD_SET) != nfsd_vers(nn, num, NFSD_TEST)) { 609 609 /* 610 610 * Either we have +4 and no minors are enabled, 611 611 * or we have -4 and at least one minor is enabled. 612 612 * In either case, propagate 'cmd' to all minors. 613 613 */ 614 614 minor = 0; 615 - while (nfsd_minorversion(minor, cmd) >= 0) 615 + while (nfsd_minorversion(nn, minor, cmd) >= 0) 616 616 minor++; 617 617 } 618 618 break; ··· 624 624 /* If all get turned off, turn them back on, as 625 625 * having no versions is BAD 626 626 */ 627 - nfsd_reset_versions(); 627 + nfsd_reset_versions(nn); 628 628 } 629 629 630 630 /* Now write current state into reply buffer */ ··· 633 633 remaining = SIMPLE_TRANSACTION_LIMIT; 634 634 for (num=2 ; num <= 4 ; num++) { 635 635 int minor; 636 - if (!nfsd_vers(num, NFSD_AVAIL)) 636 + if (!nfsd_vers(nn, num, NFSD_AVAIL)) 637 637 continue; 638 638 639 639 minor = -1; 640 640 do { 641 - len = nfsd_print_version_support(buf, remaining, 641 + len = nfsd_print_version_support(nn, buf, remaining, 642 642 sep, num, minor); 643 643 if (len >= remaining) 644 644 goto out; ··· 717 717 * a socket of a supported family/protocol, and we use it as an 718 718 * nfsd listener. 719 719 */ 720 - static ssize_t __write_ports_addfd(char *buf, struct net *net) 720 + static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred *cred) 721 721 { 722 722 char *mesg = buf; 723 723 int fd, err; ··· 736 736 if (err != 0) 737 737 return err; 738 738 739 - err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); 739 + err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred); 740 740 if (err < 0) { 741 741 nfsd_destroy(net); 742 742 return err; ··· 751 751 * A transport listener is added by writing it's transport name and 752 752 * a port number. 753 753 */ 754 - static ssize_t __write_ports_addxprt(char *buf, struct net *net) 754 + static ssize_t __write_ports_addxprt(char *buf, struct net *net, const struct cred *cred) 755 755 { 756 756 char transport[16]; 757 757 struct svc_xprt *xprt; ··· 769 769 return err; 770 770 771 771 err = svc_create_xprt(nn->nfsd_serv, transport, net, 772 - PF_INET, port, SVC_SOCK_ANONYMOUS); 772 + PF_INET, port, SVC_SOCK_ANONYMOUS, cred); 773 773 if (err < 0) 774 774 goto out_err; 775 775 776 776 err = svc_create_xprt(nn->nfsd_serv, transport, net, 777 - PF_INET6, port, SVC_SOCK_ANONYMOUS); 777 + PF_INET6, port, SVC_SOCK_ANONYMOUS, cred); 778 778 if (err < 0 && err != -EAFNOSUPPORT) 779 779 goto out_close; 780 780 ··· 799 799 return __write_ports_names(buf, net); 800 800 801 801 if (isdigit(buf[0])) 802 - return __write_ports_addfd(buf, net); 802 + return __write_ports_addfd(buf, net, file->f_cred); 803 803 804 804 if (isalpha(buf[0])) 805 - return __write_ports_addxprt(buf, net); 805 + return __write_ports_addxprt(buf, net, file->f_cred); 806 806 807 807 return -EINVAL; 808 808 } ··· 1239 1239 retval = nfsd_idmap_init(net); 1240 1240 if (retval) 1241 1241 goto out_idmap_error; 1242 + nn->nfsd_versions = NULL; 1243 + nn->nfsd4_minorversions = NULL; 1242 1244 nn->nfsd4_lease = 90; /* default lease time */ 1243 1245 nn->nfsd4_grace = 90; 1244 1246 nn->somebody_reclaimed = false; 1247 + nn->track_reclaim_completes = false; 1245 1248 nn->clverifier_counter = prandom_u32(); 1246 1249 nn->clientid_counter = prandom_u32(); 1247 1250 nn->s2s_cp_cl_id = nn->clientid_counter++; ··· 1263 1260 { 1264 1261 nfsd_idmap_shutdown(net); 1265 1262 nfsd_export_shutdown(net); 1263 + nfsd_netns_free_versions(net_generic(net, nfsd_net_id)); 1266 1264 } 1267 1265 1268 1266 static struct pernet_operations nfsd_net_ops = {
+13 -4
fs/nfsd/nfsd.h
··· 17 17 #include <linux/nfs3.h> 18 18 #include <linux/nfs4.h> 19 19 #include <linux/sunrpc/svc.h> 20 + #include <linux/sunrpc/svc_xprt.h> 20 21 #include <linux/sunrpc/msg_prot.h> 21 22 22 23 #include <uapi/linux/nfsd/debug.h> ··· 74 73 /* 75 74 * Function prototypes. 76 75 */ 77 - int nfsd_svc(int nrservs, struct net *net); 76 + int nfsd_svc(int nrservs, struct net *net, const struct cred *cred); 78 77 int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); 79 78 80 79 int nfsd_nrthreads(struct net *); ··· 99 98 #endif 100 99 #endif 101 100 101 + struct nfsd_net; 102 + 102 103 enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL }; 103 - int nfsd_vers(int vers, enum vers_op change); 104 - int nfsd_minorversion(u32 minorversion, enum vers_op change); 105 - void nfsd_reset_versions(void); 104 + int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change); 105 + int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change); 106 + void nfsd_reset_versions(struct nfsd_net *nn); 106 107 int nfsd_create_serv(struct net *net); 107 108 108 109 extern int nfsd_max_blksize; ··· 112 109 static inline int nfsd_v4client(struct svc_rqst *rq) 113 110 { 114 111 return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4; 112 + } 113 + static inline struct user_namespace * 114 + nfsd_user_namespace(const struct svc_rqst *rqstp) 115 + { 116 + const struct cred *cred = rqstp->rq_xprt->xpt_cred; 117 + return cred ? cred->user_ns : &init_user_ns; 115 118 } 116 119 117 120 /*
+220 -51
fs/nfsd/nfssvc.c
··· 32 32 33 33 extern struct svc_program nfsd_program; 34 34 static int nfsd(void *vrqstp); 35 + #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 36 + static int nfsd_acl_rpcbind_set(struct net *, 37 + const struct svc_program *, 38 + u32, int, 39 + unsigned short, 40 + unsigned short); 41 + static __be32 nfsd_acl_init_request(struct svc_rqst *, 42 + const struct svc_program *, 43 + struct svc_process_info *); 44 + #endif 45 + static int nfsd_rpcbind_set(struct net *, 46 + const struct svc_program *, 47 + u32, int, 48 + unsigned short, 49 + unsigned short); 50 + static __be32 nfsd_init_request(struct svc_rqst *, 51 + const struct svc_program *, 52 + struct svc_process_info *); 35 53 36 54 /* 37 55 * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members ··· 104 86 .pg_class = "nfsd", 105 87 .pg_stats = &nfsd_acl_svcstats, 106 88 .pg_authenticate = &svc_set_client, 89 + .pg_init_request = nfsd_acl_init_request, 90 + .pg_rpcbind_set = nfsd_acl_rpcbind_set, 107 91 }; 108 92 109 93 static struct svc_stat nfsd_acl_svcstats = { ··· 125 105 126 106 #define NFSD_MINVERS 2 127 107 #define NFSD_NRVERS ARRAY_SIZE(nfsd_version) 128 - static const struct svc_version *nfsd_versions[NFSD_NRVERS]; 129 108 130 109 struct svc_program nfsd_program = { 131 110 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) ··· 132 113 #endif 133 114 .pg_prog = NFS_PROGRAM, /* program number */ 134 115 .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ 135 - .pg_vers = nfsd_versions, /* version table */ 116 + .pg_vers = nfsd_version, /* version table */ 136 117 .pg_name = "nfsd", /* program name */ 137 118 .pg_class = "nfsd", /* authentication class */ 138 119 .pg_stats = &nfsd_svcstats, /* version table */ 139 120 .pg_authenticate = &svc_set_client, /* export authentication */ 140 - 121 + .pg_init_request = nfsd_init_request, 122 + .pg_rpcbind_set = nfsd_rpcbind_set, 141 123 }; 142 124 143 - static bool nfsd_supported_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1] = { 144 - [0] = 1, 145 - [1] = 1, 146 - [2] = 1, 147 - }; 125 + static bool 126 + nfsd_support_version(int vers) 127 + { 128 + if (vers >= NFSD_MINVERS && vers < NFSD_NRVERS) 129 + return nfsd_version[vers] != NULL; 130 + return false; 131 + } 148 132 149 - int nfsd_vers(int vers, enum vers_op change) 133 + static bool * 134 + nfsd_alloc_versions(void) 135 + { 136 + bool *vers = kmalloc_array(NFSD_NRVERS, sizeof(bool), GFP_KERNEL); 137 + unsigned i; 138 + 139 + if (vers) { 140 + /* All compiled versions are enabled by default */ 141 + for (i = 0; i < NFSD_NRVERS; i++) 142 + vers[i] = nfsd_support_version(i); 143 + } 144 + return vers; 145 + } 146 + 147 + static bool * 148 + nfsd_alloc_minorversions(void) 149 + { 150 + bool *vers = kmalloc_array(NFSD_SUPPORTED_MINOR_VERSION + 1, 151 + sizeof(bool), GFP_KERNEL); 152 + unsigned i; 153 + 154 + if (vers) { 155 + /* All minor versions are enabled by default */ 156 + for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++) 157 + vers[i] = nfsd_support_version(4); 158 + } 159 + return vers; 160 + } 161 + 162 + void 163 + nfsd_netns_free_versions(struct nfsd_net *nn) 164 + { 165 + kfree(nn->nfsd_versions); 166 + kfree(nn->nfsd4_minorversions); 167 + nn->nfsd_versions = NULL; 168 + nn->nfsd4_minorversions = NULL; 169 + } 170 + 171 + static void 172 + nfsd_netns_init_versions(struct nfsd_net *nn) 173 + { 174 + if (!nn->nfsd_versions) { 175 + nn->nfsd_versions = nfsd_alloc_versions(); 176 + nn->nfsd4_minorversions = nfsd_alloc_minorversions(); 177 + if (!nn->nfsd_versions || !nn->nfsd4_minorversions) 178 + nfsd_netns_free_versions(nn); 179 + } 180 + } 181 + 182 + int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change) 150 183 { 151 184 if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS) 152 185 return 0; 153 186 switch(change) { 154 187 case NFSD_SET: 155 - nfsd_versions[vers] = nfsd_version[vers]; 156 - #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 157 - if (vers < NFSD_ACL_NRVERS) 158 - nfsd_acl_versions[vers] = nfsd_acl_version[vers]; 159 - #endif 188 + if (nn->nfsd_versions) 189 + nn->nfsd_versions[vers] = nfsd_support_version(vers); 160 190 break; 161 191 case NFSD_CLEAR: 162 - nfsd_versions[vers] = NULL; 163 - #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 164 - if (vers < NFSD_ACL_NRVERS) 165 - nfsd_acl_versions[vers] = NULL; 166 - #endif 192 + nfsd_netns_init_versions(nn); 193 + if (nn->nfsd_versions) 194 + nn->nfsd_versions[vers] = false; 167 195 break; 168 196 case NFSD_TEST: 169 - return nfsd_versions[vers] != NULL; 197 + if (nn->nfsd_versions) 198 + return nn->nfsd_versions[vers]; 199 + /* Fallthrough */ 170 200 case NFSD_AVAIL: 171 - return nfsd_version[vers] != NULL; 201 + return nfsd_support_version(vers); 172 202 } 173 203 return 0; 174 204 } 175 205 176 206 static void 177 - nfsd_adjust_nfsd_versions4(void) 207 + nfsd_adjust_nfsd_versions4(struct nfsd_net *nn) 178 208 { 179 209 unsigned i; 180 210 181 211 for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++) { 182 - if (nfsd_supported_minorversions[i]) 212 + if (nn->nfsd4_minorversions[i]) 183 213 return; 184 214 } 185 - nfsd_vers(4, NFSD_CLEAR); 215 + nfsd_vers(nn, 4, NFSD_CLEAR); 186 216 } 187 217 188 - int nfsd_minorversion(u32 minorversion, enum vers_op change) 218 + int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change) 189 219 { 190 220 if (minorversion > NFSD_SUPPORTED_MINOR_VERSION && 191 221 change != NFSD_AVAIL) 192 222 return -1; 223 + 193 224 switch(change) { 194 225 case NFSD_SET: 195 - nfsd_supported_minorversions[minorversion] = true; 196 - nfsd_vers(4, NFSD_SET); 226 + if (nn->nfsd4_minorversions) { 227 + nfsd_vers(nn, 4, NFSD_SET); 228 + nn->nfsd4_minorversions[minorversion] = 229 + nfsd_vers(nn, 4, NFSD_TEST); 230 + } 197 231 break; 198 232 case NFSD_CLEAR: 199 - nfsd_supported_minorversions[minorversion] = false; 200 - nfsd_adjust_nfsd_versions4(); 233 + nfsd_netns_init_versions(nn); 234 + if (nn->nfsd4_minorversions) { 235 + nn->nfsd4_minorversions[minorversion] = false; 236 + nfsd_adjust_nfsd_versions4(nn); 237 + } 201 238 break; 202 239 case NFSD_TEST: 203 - return nfsd_supported_minorversions[minorversion]; 240 + if (nn->nfsd4_minorversions) 241 + return nn->nfsd4_minorversions[minorversion]; 242 + return nfsd_vers(nn, 4, NFSD_TEST); 204 243 case NFSD_AVAIL: 205 - return minorversion <= NFSD_SUPPORTED_MINOR_VERSION; 244 + return minorversion <= NFSD_SUPPORTED_MINOR_VERSION && 245 + nfsd_vers(nn, 4, NFSD_AVAIL); 206 246 } 207 247 return 0; 208 248 } ··· 283 205 return rv; 284 206 } 285 207 286 - static int nfsd_init_socks(struct net *net) 208 + static int nfsd_init_socks(struct net *net, const struct cred *cred) 287 209 { 288 210 int error; 289 211 struct nfsd_net *nn = net_generic(net, nfsd_net_id); ··· 292 214 return 0; 293 215 294 216 error = svc_create_xprt(nn->nfsd_serv, "udp", net, PF_INET, NFS_PORT, 295 - SVC_SOCK_DEFAULTS); 217 + SVC_SOCK_DEFAULTS, cred); 296 218 if (error < 0) 297 219 return error; 298 220 299 221 error = svc_create_xprt(nn->nfsd_serv, "tcp", net, PF_INET, NFS_PORT, 300 - SVC_SOCK_DEFAULTS); 222 + SVC_SOCK_DEFAULTS, cred); 301 223 if (error < 0) 302 224 return error; 303 225 ··· 343 265 nfsd_racache_shutdown(); 344 266 } 345 267 346 - static bool nfsd_needs_lockd(void) 268 + static bool nfsd_needs_lockd(struct nfsd_net *nn) 347 269 { 348 - #if defined(CONFIG_NFSD_V3) 349 - return (nfsd_versions[2] != NULL) || (nfsd_versions[3] != NULL); 350 - #else 351 - return (nfsd_versions[2] != NULL); 352 - #endif 270 + return nfsd_vers(nn, 2, NFSD_TEST) || nfsd_vers(nn, 3, NFSD_TEST); 353 271 } 354 272 355 - static int nfsd_startup_net(int nrservs, struct net *net) 273 + static int nfsd_startup_net(int nrservs, struct net *net, const struct cred *cred) 356 274 { 357 275 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 358 276 int ret; ··· 359 285 ret = nfsd_startup_generic(nrservs); 360 286 if (ret) 361 287 return ret; 362 - ret = nfsd_init_socks(net); 288 + ret = nfsd_init_socks(net, cred); 363 289 if (ret) 364 290 goto out_socks; 365 291 366 - if (nfsd_needs_lockd() && !nn->lockd_up) { 367 - ret = lockd_up(net); 292 + if (nfsd_needs_lockd(nn) && !nn->lockd_up) { 293 + ret = lockd_up(net, cred); 368 294 if (ret) 369 295 goto out_socks; 370 296 nn->lockd_up = 1; ··· 496 422 nfsd_export_flush(net); 497 423 } 498 424 499 - void nfsd_reset_versions(void) 425 + void nfsd_reset_versions(struct nfsd_net *nn) 500 426 { 501 427 int i; 502 428 503 429 for (i = 0; i < NFSD_NRVERS; i++) 504 - if (nfsd_vers(i, NFSD_TEST)) 430 + if (nfsd_vers(nn, i, NFSD_TEST)) 505 431 return; 506 432 507 433 for (i = 0; i < NFSD_NRVERS; i++) 508 434 if (i != 4) 509 - nfsd_vers(i, NFSD_SET); 435 + nfsd_vers(nn, i, NFSD_SET); 510 436 else { 511 437 int minor = 0; 512 - while (nfsd_minorversion(minor, NFSD_SET) >= 0) 438 + while (nfsd_minorversion(nn, minor, NFSD_SET) >= 0) 513 439 minor++; 514 440 } 515 441 } ··· 577 503 } 578 504 if (nfsd_max_blksize == 0) 579 505 nfsd_max_blksize = nfsd_get_default_max_blksize(); 580 - nfsd_reset_versions(); 506 + nfsd_reset_versions(nn); 581 507 nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, 582 508 &nfsd_thread_sv_ops); 583 509 if (nn->nfsd_serv == NULL) ··· 697 623 * this is the first time nrservs is nonzero. 698 624 */ 699 625 int 700 - nfsd_svc(int nrservs, struct net *net) 626 + nfsd_svc(int nrservs, struct net *net, const struct cred *cred) 701 627 { 702 628 int error; 703 629 bool nfsd_up_before; ··· 719 645 720 646 nfsd_up_before = nn->nfsd_net_up; 721 647 722 - error = nfsd_startup_net(nrservs, net); 648 + error = nfsd_startup_net(nrservs, net, cred); 723 649 if (error) 724 650 goto out_destroy; 725 651 error = nn->nfsd_serv->sv_ops->svo_setup(nn->nfsd_serv, ··· 741 667 return error; 742 668 } 743 669 670 + #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 671 + static bool 672 + nfsd_support_acl_version(int vers) 673 + { 674 + if (vers >= NFSD_ACL_MINVERS && vers < NFSD_ACL_NRVERS) 675 + return nfsd_acl_version[vers] != NULL; 676 + return false; 677 + } 678 + 679 + static int 680 + nfsd_acl_rpcbind_set(struct net *net, const struct svc_program *progp, 681 + u32 version, int family, unsigned short proto, 682 + unsigned short port) 683 + { 684 + if (!nfsd_support_acl_version(version) || 685 + !nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST)) 686 + return 0; 687 + return svc_generic_rpcbind_set(net, progp, version, family, 688 + proto, port); 689 + } 690 + 691 + static __be32 692 + nfsd_acl_init_request(struct svc_rqst *rqstp, 693 + const struct svc_program *progp, 694 + struct svc_process_info *ret) 695 + { 696 + struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 697 + int i; 698 + 699 + if (likely(nfsd_support_acl_version(rqstp->rq_vers) && 700 + nfsd_vers(nn, rqstp->rq_vers, NFSD_TEST))) 701 + return svc_generic_init_request(rqstp, progp, ret); 702 + 703 + ret->mismatch.lovers = NFSD_ACL_NRVERS; 704 + for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) { 705 + if (nfsd_support_acl_version(rqstp->rq_vers) && 706 + nfsd_vers(nn, i, NFSD_TEST)) { 707 + ret->mismatch.lovers = i; 708 + break; 709 + } 710 + } 711 + if (ret->mismatch.lovers == NFSD_ACL_NRVERS) 712 + return rpc_prog_unavail; 713 + ret->mismatch.hivers = NFSD_ACL_MINVERS; 714 + for (i = NFSD_ACL_NRVERS - 1; i >= NFSD_ACL_MINVERS; i--) { 715 + if (nfsd_support_acl_version(rqstp->rq_vers) && 716 + nfsd_vers(nn, i, NFSD_TEST)) { 717 + ret->mismatch.hivers = i; 718 + break; 719 + } 720 + } 721 + return rpc_prog_mismatch; 722 + } 723 + #endif 724 + 725 + static int 726 + nfsd_rpcbind_set(struct net *net, const struct svc_program *progp, 727 + u32 version, int family, unsigned short proto, 728 + unsigned short port) 729 + { 730 + if (!nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST)) 731 + return 0; 732 + return svc_generic_rpcbind_set(net, progp, version, family, 733 + proto, port); 734 + } 735 + 736 + static __be32 737 + nfsd_init_request(struct svc_rqst *rqstp, 738 + const struct svc_program *progp, 739 + struct svc_process_info *ret) 740 + { 741 + struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 742 + int i; 743 + 744 + if (likely(nfsd_vers(nn, rqstp->rq_vers, NFSD_TEST))) 745 + return svc_generic_init_request(rqstp, progp, ret); 746 + 747 + ret->mismatch.lovers = NFSD_NRVERS; 748 + for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) { 749 + if (nfsd_vers(nn, i, NFSD_TEST)) { 750 + ret->mismatch.lovers = i; 751 + break; 752 + } 753 + } 754 + if (ret->mismatch.lovers == NFSD_NRVERS) 755 + return rpc_prog_unavail; 756 + ret->mismatch.hivers = NFSD_MINVERS; 757 + for (i = NFSD_NRVERS - 1; i >= NFSD_MINVERS; i--) { 758 + if (nfsd_vers(nn, i, NFSD_TEST)) { 759 + ret->mismatch.hivers = i; 760 + break; 761 + } 762 + } 763 + return rpc_prog_mismatch; 764 + } 744 765 745 766 /* 746 767 * This is the NFS server kernel thread
+9 -8
fs/nfsd/nfsxdr.c
··· 71 71 } 72 72 73 73 static __be32 * 74 - decode_sattr(__be32 *p, struct iattr *iap) 74 + decode_sattr(__be32 *p, struct iattr *iap, struct user_namespace *userns) 75 75 { 76 76 u32 tmp, tmp1; 77 77 ··· 86 86 iap->ia_mode = tmp; 87 87 } 88 88 if ((tmp = ntohl(*p++)) != (u32)-1) { 89 - iap->ia_uid = make_kuid(&init_user_ns, tmp); 89 + iap->ia_uid = make_kuid(userns, tmp); 90 90 if (uid_valid(iap->ia_uid)) 91 91 iap->ia_valid |= ATTR_UID; 92 92 } 93 93 if ((tmp = ntohl(*p++)) != (u32)-1) { 94 - iap->ia_gid = make_kgid(&init_user_ns, tmp); 94 + iap->ia_gid = make_kgid(userns, tmp); 95 95 if (gid_valid(iap->ia_gid)) 96 96 iap->ia_valid |= ATTR_GID; 97 97 } ··· 129 129 encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, 130 130 struct kstat *stat) 131 131 { 132 + struct user_namespace *userns = nfsd_user_namespace(rqstp); 132 133 struct dentry *dentry = fhp->fh_dentry; 133 134 int type; 134 135 struct timespec64 time; ··· 140 139 *p++ = htonl(nfs_ftypes[type >> 12]); 141 140 *p++ = htonl((u32) stat->mode); 142 141 *p++ = htonl((u32) stat->nlink); 143 - *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); 144 - *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); 142 + *p++ = htonl((u32) from_kuid_munged(userns, stat->uid)); 143 + *p++ = htonl((u32) from_kgid_munged(userns, stat->gid)); 145 144 146 145 if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) { 147 146 *p++ = htonl(NFS_MAXPATHLEN); ··· 217 216 p = decode_fh(p, &args->fh); 218 217 if (!p) 219 218 return 0; 220 - p = decode_sattr(p, &args->attrs); 219 + p = decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp)); 221 220 222 221 return xdr_argsize_check(rqstp, p); 223 222 } ··· 320 319 if ( !(p = decode_fh(p, &args->fh)) 321 320 || !(p = decode_filename(p, &args->name, &args->len))) 322 321 return 0; 323 - p = decode_sattr(p, &args->attrs); 322 + p = decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp)); 324 323 325 324 return xdr_argsize_check(rqstp, p); 326 325 } ··· 399 398 return 0; 400 399 p += xdrlen; 401 400 } 402 - decode_sattr(p, &args->attrs); 401 + decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp)); 403 402 404 403 return 1; 405 404 }
+4 -4
fs/nfsd/state.h
··· 368 368 struct nfs4_client_reclaim { 369 369 struct list_head cr_strhash; /* hash by cr_name */ 370 370 struct nfs4_client *cr_clp; /* pointer to associated clp */ 371 - char cr_recdir[HEXDIR_LEN]; /* recover dir */ 371 + struct xdr_netobj cr_name; /* recovery dir name */ 372 372 }; 373 373 374 374 /* A reasonable value for REPLAY_ISIZE was estimated as follows: ··· 620 620 void nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid); 621 621 void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *); 622 622 extern void nfs4_release_reclaim(struct nfsd_net *); 623 - extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir, 623 + extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct xdr_netobj name, 624 624 struct nfsd_net *nn); 625 625 extern __be32 nfs4_check_open_reclaim(clientid_t *clid, 626 626 struct nfsd4_compound_state *cstate, struct nfsd_net *nn); ··· 635 635 extern void nfsd4_shutdown_callback(struct nfs4_client *); 636 636 extern void nfsd4_shutdown_copy(struct nfs4_client *clp); 637 637 extern void nfsd4_prepare_cb_recall(struct nfs4_delegation *dp); 638 - extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name, 638 + extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(struct xdr_netobj name, 639 639 struct nfsd_net *nn); 640 - extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn); 640 + extern bool nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn); 641 641 642 642 struct nfs4_file *find_file(struct knfsd_fh *fh); 643 643 void put_nfs4_file(struct nfs4_file *fi);
+5 -3
fs/nfsd/vfs.c
··· 1786 1786 rdentry = lookup_one_len(fname, dentry, flen); 1787 1787 host_err = PTR_ERR(rdentry); 1788 1788 if (IS_ERR(rdentry)) 1789 - goto out_nfserr; 1789 + goto out_drop_write; 1790 1790 1791 1791 if (d_really_is_negative(rdentry)) { 1792 1792 dput(rdentry); 1793 - err = nfserr_noent; 1794 - goto out; 1793 + host_err = -ENOENT; 1794 + goto out_drop_write; 1795 1795 } 1796 1796 1797 1797 if (!type) ··· 1805 1805 host_err = commit_metadata(fhp); 1806 1806 dput(rdentry); 1807 1807 1808 + out_drop_write: 1809 + fh_drop_write(fhp); 1808 1810 out_nfserr: 1809 1811 err = nfserrno(host_err); 1810 1812 out:
+4 -1
fs/nfsd/vfs.h
··· 120 120 121 121 static inline int fh_want_write(struct svc_fh *fh) 122 122 { 123 - int ret = mnt_want_write(fh->fh_export->ex_path.mnt); 123 + int ret; 124 124 125 + if (fh->fh_want_write) 126 + return 0; 127 + ret = mnt_want_write(fh->fh_export->ex_path.mnt); 125 128 if (!ret) 126 129 fh->fh_want_write = true; 127 130 return ret;
+1 -1
include/linux/lockd/bind.h
··· 76 76 }; 77 77 78 78 extern int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl, void *data); 79 - extern int lockd_up(struct net *net); 79 + extern int lockd_up(struct net *net, const struct cred *cred); 80 80 extern void lockd_down(struct net *net); 81 81 82 82 #endif /* LINUX_LOCKD_BIND_H */
+33
include/linux/sunrpc/svc.h
··· 271 271 #define RQ_VICTIM (5) /* about to be shut down */ 272 272 #define RQ_BUSY (6) /* request is busy */ 273 273 #define RQ_DATA (7) /* request has data */ 274 + #define RQ_AUTHERR (8) /* Request status is auth error */ 274 275 unsigned long rq_flags; /* flags field */ 275 276 ktime_t rq_qtime; /* enqueue time */ 276 277 ··· 383 382 __be32 args[0]; 384 383 }; 385 384 385 + struct svc_process_info { 386 + union { 387 + int (*dispatch)(struct svc_rqst *, __be32 *); 388 + struct { 389 + unsigned int lovers; 390 + unsigned int hivers; 391 + } mismatch; 392 + }; 393 + }; 394 + 386 395 /* 387 396 * List of RPC programs on the same transport endpoint 388 397 */ ··· 407 396 char * pg_class; /* class name: services sharing authentication */ 408 397 struct svc_stat * pg_stats; /* rpc statistics */ 409 398 int (*pg_authenticate)(struct svc_rqst *); 399 + __be32 (*pg_init_request)(struct svc_rqst *, 400 + const struct svc_program *, 401 + struct svc_process_info *); 402 + int (*pg_rpcbind_set)(struct net *net, 403 + const struct svc_program *, 404 + u32 version, int family, 405 + unsigned short proto, 406 + unsigned short port); 410 407 }; 411 408 412 409 /* ··· 523 504 char *svc_fill_symlink_pathname(struct svc_rqst *rqstp, 524 505 struct kvec *first, void *p, 525 506 size_t total); 507 + __be32 svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err); 508 + __be32 svc_generic_init_request(struct svc_rqst *rqstp, 509 + const struct svc_program *progp, 510 + struct svc_process_info *procinfo); 511 + int svc_generic_rpcbind_set(struct net *net, 512 + const struct svc_program *progp, 513 + u32 version, int family, 514 + unsigned short proto, 515 + unsigned short port); 516 + int svc_rpcbind_set_version(struct net *net, 517 + const struct svc_program *progp, 518 + u32 version, int family, 519 + unsigned short proto, 520 + unsigned short port); 526 521 527 522 #define RPC_MAX_ADDRBUFLEN (63U) 528 523
+3 -1
include/linux/sunrpc/svc_xprt.h
··· 86 86 struct list_head xpt_users; /* callbacks on free */ 87 87 88 88 struct net *xpt_net; 89 + const struct cred *xpt_cred; 89 90 struct rpc_xprt *xpt_bc_xprt; /* NFSv4.1 backchannel */ 90 91 struct rpc_xprt_switch *xpt_bc_xps; /* NFSv4.1 backchannel */ 91 92 }; ··· 120 119 void svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *, 121 120 struct svc_serv *); 122 121 int svc_create_xprt(struct svc_serv *, const char *, struct net *, 123 - const int, const unsigned short, int); 122 + const int, const unsigned short, int, 123 + const struct cred *); 124 124 void svc_xprt_do_enqueue(struct svc_xprt *xprt); 125 125 void svc_xprt_enqueue(struct svc_xprt *xprt); 126 126 void svc_xprt_put(struct svc_xprt *xprt);
+2 -1
include/linux/sunrpc/svcsock.h
··· 59 59 void svc_sock_update_bufs(struct svc_serv *serv); 60 60 bool svc_alien_sock(struct net *net, int fd); 61 61 int svc_addsock(struct svc_serv *serv, const int fd, 62 - char *name_return, const size_t len); 62 + char *name_return, const size_t len, 63 + const struct cred *cred); 63 64 void svc_init_xprt_sock(void); 64 65 void svc_cleanup_xprt_sock(void); 65 66 struct svc_xprt *svc_sock_create(struct svc_serv *serv, int prot);
+1
include/uapi/linux/nfsd/cld.h
··· 36 36 Cld_Remove, /* remove record of this cm_id */ 37 37 Cld_Check, /* is this cm_id allowed? */ 38 38 Cld_GraceDone, /* grace period is complete */ 39 + Cld_GraceStart, 39 40 }; 40 41 41 42 /* representation of long-form NFSv4 client ID */
+3 -3
net/sunrpc/auth_gss/svcauth_gss.c
··· 474 474 * treatment so are checked for validity here.) 475 475 */ 476 476 /* uid */ 477 - rsci.cred.cr_uid = make_kuid(&init_user_ns, id); 477 + rsci.cred.cr_uid = make_kuid(current_user_ns(), id); 478 478 479 479 /* gid */ 480 480 if (get_int(&mesg, &id)) 481 481 goto out; 482 - rsci.cred.cr_gid = make_kgid(&init_user_ns, id); 482 + rsci.cred.cr_gid = make_kgid(current_user_ns(), id); 483 483 484 484 /* number of additional gid's */ 485 485 if (get_int(&mesg, &N)) ··· 497 497 kgid_t kgid; 498 498 if (get_int(&mesg, &id)) 499 499 goto out; 500 - kgid = make_kgid(&init_user_ns, id); 500 + kgid = make_kgid(current_user_ns(), id); 501 501 if (!gid_valid(kgid)) 502 502 goto out; 503 503 rsci.cred.cr_group_info->gid[i] = kgid;
+3 -1
net/sunrpc/cache.c
··· 40 40 41 41 static bool cache_defer_req(struct cache_req *req, struct cache_head *item); 42 42 static void cache_revisit_request(struct cache_head *item); 43 + static bool cache_listeners_exist(struct cache_detail *detail); 43 44 44 45 static void cache_init(struct cache_head *h, struct cache_detail *detail) 45 46 { ··· 307 306 cache_fresh_unlocked(h, detail); 308 307 break; 309 308 } 310 - } 309 + } else if (!cache_listeners_exist(detail)) 310 + rv = try_to_negate_entry(detail, h); 311 311 } 312 312 313 313 if (rv == -EAGAIN) {
+199 -101
net/sunrpc/svc.c
··· 993 993 return error; 994 994 } 995 995 996 + int svc_rpcbind_set_version(struct net *net, 997 + const struct svc_program *progp, 998 + u32 version, int family, 999 + unsigned short proto, 1000 + unsigned short port) 1001 + { 1002 + dprintk("svc: svc_register(%sv%d, %s, %u, %u)\n", 1003 + progp->pg_name, version, 1004 + proto == IPPROTO_UDP? "udp" : "tcp", 1005 + port, family); 1006 + 1007 + return __svc_register(net, progp->pg_name, progp->pg_prog, 1008 + version, family, proto, port); 1009 + 1010 + } 1011 + EXPORT_SYMBOL_GPL(svc_rpcbind_set_version); 1012 + 1013 + int svc_generic_rpcbind_set(struct net *net, 1014 + const struct svc_program *progp, 1015 + u32 version, int family, 1016 + unsigned short proto, 1017 + unsigned short port) 1018 + { 1019 + const struct svc_version *vers = progp->pg_vers[version]; 1020 + int error; 1021 + 1022 + if (vers == NULL) 1023 + return 0; 1024 + 1025 + if (vers->vs_hidden) { 1026 + dprintk("svc: svc_register(%sv%d, %s, %u, %u)" 1027 + " (but not telling portmap)\n", 1028 + progp->pg_name, version, 1029 + proto == IPPROTO_UDP? "udp" : "tcp", 1030 + port, family); 1031 + return 0; 1032 + } 1033 + 1034 + /* 1035 + * Don't register a UDP port if we need congestion 1036 + * control. 1037 + */ 1038 + if (vers->vs_need_cong_ctrl && proto == IPPROTO_UDP) 1039 + return 0; 1040 + 1041 + error = svc_rpcbind_set_version(net, progp, version, 1042 + family, proto, port); 1043 + 1044 + return (vers->vs_rpcb_optnl) ? 0 : error; 1045 + } 1046 + EXPORT_SYMBOL_GPL(svc_generic_rpcbind_set); 1047 + 996 1048 /** 997 1049 * svc_register - register an RPC service with the local portmapper 998 1050 * @serv: svc_serv struct for the service to register ··· 1060 1008 const unsigned short port) 1061 1009 { 1062 1010 struct svc_program *progp; 1063 - const struct svc_version *vers; 1064 1011 unsigned int i; 1065 1012 int error = 0; 1066 1013 ··· 1069 1018 1070 1019 for (progp = serv->sv_program; progp; progp = progp->pg_next) { 1071 1020 for (i = 0; i < progp->pg_nvers; i++) { 1072 - vers = progp->pg_vers[i]; 1073 - if (vers == NULL) 1074 - continue; 1075 1021 1076 - dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n", 1077 - progp->pg_name, 1078 - i, 1079 - proto == IPPROTO_UDP? "udp" : "tcp", 1080 - port, 1081 - family, 1082 - vers->vs_hidden ? 1083 - " (but not telling portmap)" : ""); 1084 - 1085 - if (vers->vs_hidden) 1086 - continue; 1087 - 1088 - /* 1089 - * Don't register a UDP port if we need congestion 1090 - * control. 1091 - */ 1092 - if (vers->vs_need_cong_ctrl && proto == IPPROTO_UDP) 1093 - continue; 1094 - 1095 - error = __svc_register(net, progp->pg_name, progp->pg_prog, 1096 - i, family, proto, port); 1097 - 1098 - if (vers->vs_rpcb_optnl) { 1099 - error = 0; 1100 - continue; 1101 - } 1102 - 1022 + error = progp->pg_rpcbind_set(net, progp, i, 1023 + family, proto, port); 1103 1024 if (error < 0) { 1104 1025 printk(KERN_WARNING "svc: failed to register " 1105 1026 "%sv%u RPC service (errno %d).\n", ··· 1167 1144 static __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {} 1168 1145 #endif 1169 1146 1147 + __be32 1148 + svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err) 1149 + { 1150 + set_bit(RQ_AUTHERR, &rqstp->rq_flags); 1151 + return auth_err; 1152 + } 1153 + EXPORT_SYMBOL_GPL(svc_return_autherr); 1154 + 1155 + static __be32 1156 + svc_get_autherr(struct svc_rqst *rqstp, __be32 *statp) 1157 + { 1158 + if (test_and_clear_bit(RQ_AUTHERR, &rqstp->rq_flags)) 1159 + return *statp; 1160 + return rpc_auth_ok; 1161 + } 1162 + 1163 + static int 1164 + svc_generic_dispatch(struct svc_rqst *rqstp, __be32 *statp) 1165 + { 1166 + struct kvec *argv = &rqstp->rq_arg.head[0]; 1167 + struct kvec *resv = &rqstp->rq_res.head[0]; 1168 + const struct svc_procedure *procp = rqstp->rq_procinfo; 1169 + 1170 + /* 1171 + * Decode arguments 1172 + * XXX: why do we ignore the return value? 1173 + */ 1174 + if (procp->pc_decode && 1175 + !procp->pc_decode(rqstp, argv->iov_base)) { 1176 + *statp = rpc_garbage_args; 1177 + return 1; 1178 + } 1179 + 1180 + *statp = procp->pc_func(rqstp); 1181 + 1182 + if (*statp == rpc_drop_reply || 1183 + test_bit(RQ_DROPME, &rqstp->rq_flags)) 1184 + return 0; 1185 + 1186 + if (test_bit(RQ_AUTHERR, &rqstp->rq_flags)) 1187 + return 1; 1188 + 1189 + if (*statp != rpc_success) 1190 + return 1; 1191 + 1192 + /* Encode reply */ 1193 + if (procp->pc_encode && 1194 + !procp->pc_encode(rqstp, resv->iov_base + resv->iov_len)) { 1195 + dprintk("svc: failed to encode reply\n"); 1196 + /* serv->sv_stats->rpcsystemerr++; */ 1197 + *statp = rpc_system_err; 1198 + } 1199 + return 1; 1200 + } 1201 + 1202 + __be32 1203 + svc_generic_init_request(struct svc_rqst *rqstp, 1204 + const struct svc_program *progp, 1205 + struct svc_process_info *ret) 1206 + { 1207 + const struct svc_version *versp = NULL; /* compiler food */ 1208 + const struct svc_procedure *procp = NULL; 1209 + 1210 + if (rqstp->rq_vers >= progp->pg_nvers ) 1211 + goto err_bad_vers; 1212 + versp = progp->pg_vers[rqstp->rq_vers]; 1213 + if (!versp) 1214 + goto err_bad_vers; 1215 + 1216 + /* 1217 + * Some protocol versions (namely NFSv4) require some form of 1218 + * congestion control. (See RFC 7530 section 3.1 paragraph 2) 1219 + * In other words, UDP is not allowed. We mark those when setting 1220 + * up the svc_xprt, and verify that here. 1221 + * 1222 + * The spec is not very clear about what error should be returned 1223 + * when someone tries to access a server that is listening on UDP 1224 + * for lower versions. RPC_PROG_MISMATCH seems to be the closest 1225 + * fit. 1226 + */ 1227 + if (versp->vs_need_cong_ctrl && rqstp->rq_xprt && 1228 + !test_bit(XPT_CONG_CTRL, &rqstp->rq_xprt->xpt_flags)) 1229 + goto err_bad_vers; 1230 + 1231 + if (rqstp->rq_proc >= versp->vs_nproc) 1232 + goto err_bad_proc; 1233 + rqstp->rq_procinfo = procp = &versp->vs_proc[rqstp->rq_proc]; 1234 + if (!procp) 1235 + goto err_bad_proc; 1236 + 1237 + /* Initialize storage for argp and resp */ 1238 + memset(rqstp->rq_argp, 0, procp->pc_argsize); 1239 + memset(rqstp->rq_resp, 0, procp->pc_ressize); 1240 + 1241 + /* Bump per-procedure stats counter */ 1242 + versp->vs_count[rqstp->rq_proc]++; 1243 + 1244 + ret->dispatch = versp->vs_dispatch; 1245 + return rpc_success; 1246 + err_bad_vers: 1247 + ret->mismatch.lovers = progp->pg_lovers; 1248 + ret->mismatch.hivers = progp->pg_hivers; 1249 + return rpc_prog_mismatch; 1250 + err_bad_proc: 1251 + return rpc_proc_unavail; 1252 + } 1253 + EXPORT_SYMBOL_GPL(svc_generic_init_request); 1254 + 1170 1255 /* 1171 1256 * Common routine for processing the RPC request. 1172 1257 */ ··· 1282 1151 svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) 1283 1152 { 1284 1153 struct svc_program *progp; 1285 - const struct svc_version *versp = NULL; /* compiler food */ 1286 1154 const struct svc_procedure *procp = NULL; 1287 1155 struct svc_serv *serv = rqstp->rq_server; 1156 + struct svc_process_info process; 1288 1157 __be32 *statp; 1289 - u32 prog, vers, proc; 1158 + u32 prog, vers; 1290 1159 __be32 auth_stat, rpc_stat; 1291 1160 int auth_res; 1292 1161 __be32 *reply_statp; ··· 1318 1187 svc_putnl(resv, 0); /* ACCEPT */ 1319 1188 1320 1189 rqstp->rq_prog = prog = svc_getnl(argv); /* program number */ 1321 - rqstp->rq_vers = vers = svc_getnl(argv); /* version number */ 1322 - rqstp->rq_proc = proc = svc_getnl(argv); /* procedure number */ 1190 + rqstp->rq_vers = svc_getnl(argv); /* version number */ 1191 + rqstp->rq_proc = svc_getnl(argv); /* procedure number */ 1323 1192 1324 1193 for (progp = serv->sv_program; progp; progp = progp->pg_next) 1325 1194 if (prog == progp->pg_prog) ··· 1357 1226 if (progp == NULL) 1358 1227 goto err_bad_prog; 1359 1228 1360 - if (vers >= progp->pg_nvers || 1361 - !(versp = progp->pg_vers[vers])) 1229 + rpc_stat = progp->pg_init_request(rqstp, progp, &process); 1230 + switch (rpc_stat) { 1231 + case rpc_success: 1232 + break; 1233 + case rpc_prog_unavail: 1234 + goto err_bad_prog; 1235 + case rpc_prog_mismatch: 1362 1236 goto err_bad_vers; 1363 - 1364 - /* 1365 - * Some protocol versions (namely NFSv4) require some form of 1366 - * congestion control. (See RFC 7530 section 3.1 paragraph 2) 1367 - * In other words, UDP is not allowed. We mark those when setting 1368 - * up the svc_xprt, and verify that here. 1369 - * 1370 - * The spec is not very clear about what error should be returned 1371 - * when someone tries to access a server that is listening on UDP 1372 - * for lower versions. RPC_PROG_MISMATCH seems to be the closest 1373 - * fit. 1374 - */ 1375 - if (versp->vs_need_cong_ctrl && rqstp->rq_xprt && 1376 - !test_bit(XPT_CONG_CTRL, &rqstp->rq_xprt->xpt_flags)) 1377 - goto err_bad_vers; 1378 - 1379 - procp = versp->vs_proc + proc; 1380 - if (proc >= versp->vs_nproc || !procp->pc_func) 1237 + case rpc_proc_unavail: 1381 1238 goto err_bad_proc; 1382 - rqstp->rq_procinfo = procp; 1239 + } 1240 + 1241 + procp = rqstp->rq_procinfo; 1242 + /* Should this check go into the dispatcher? */ 1243 + if (!procp || !procp->pc_func) 1244 + goto err_bad_proc; 1383 1245 1384 1246 /* Syntactic check complete */ 1385 1247 serv->sv_stats->rpccnt++; ··· 1382 1258 statp = resv->iov_base +resv->iov_len; 1383 1259 svc_putnl(resv, RPC_SUCCESS); 1384 1260 1385 - /* Bump per-procedure stats counter */ 1386 - versp->vs_count[proc]++; 1387 - 1388 - /* Initialize storage for argp and resp */ 1389 - memset(rqstp->rq_argp, 0, procp->pc_argsize); 1390 - memset(rqstp->rq_resp, 0, procp->pc_ressize); 1391 - 1392 1261 /* un-reserve some of the out-queue now that we have a 1393 1262 * better idea of reply size 1394 1263 */ ··· 1389 1272 svc_reserve_auth(rqstp, procp->pc_xdrressize<<2); 1390 1273 1391 1274 /* Call the function that processes the request. */ 1392 - if (!versp->vs_dispatch) { 1393 - /* 1394 - * Decode arguments 1395 - * XXX: why do we ignore the return value? 1396 - */ 1397 - if (procp->pc_decode && 1398 - !procp->pc_decode(rqstp, argv->iov_base)) 1275 + if (!process.dispatch) { 1276 + if (!svc_generic_dispatch(rqstp, statp)) 1277 + goto release_dropit; 1278 + if (*statp == rpc_garbage_args) 1399 1279 goto err_garbage; 1400 - 1401 - *statp = procp->pc_func(rqstp); 1402 - 1403 - /* Encode reply */ 1404 - if (*statp == rpc_drop_reply || 1405 - test_bit(RQ_DROPME, &rqstp->rq_flags)) { 1406 - if (procp->pc_release) 1407 - procp->pc_release(rqstp); 1408 - goto dropit; 1409 - } 1410 - if (*statp == rpc_autherr_badcred) { 1411 - if (procp->pc_release) 1412 - procp->pc_release(rqstp); 1413 - goto err_bad_auth; 1414 - } 1415 - if (*statp == rpc_success && procp->pc_encode && 1416 - !procp->pc_encode(rqstp, resv->iov_base + resv->iov_len)) { 1417 - dprintk("svc: failed to encode reply\n"); 1418 - /* serv->sv_stats->rpcsystemerr++; */ 1419 - *statp = rpc_system_err; 1420 - } 1280 + auth_stat = svc_get_autherr(rqstp, statp); 1281 + if (auth_stat != rpc_auth_ok) 1282 + goto err_release_bad_auth; 1421 1283 } else { 1422 1284 dprintk("svc: calling dispatcher\n"); 1423 - if (!versp->vs_dispatch(rqstp, statp)) { 1424 - /* Release reply info */ 1425 - if (procp->pc_release) 1426 - procp->pc_release(rqstp); 1427 - goto dropit; 1428 - } 1285 + if (!process.dispatch(rqstp, statp)) 1286 + goto release_dropit; /* Release reply info */ 1429 1287 } 1430 1288 1431 1289 /* Check RPC status result */ ··· 1419 1327 goto close; 1420 1328 return 1; /* Caller can now send it */ 1421 1329 1330 + release_dropit: 1331 + if (procp->pc_release) 1332 + procp->pc_release(rqstp); 1422 1333 dropit: 1423 1334 svc_authorise(rqstp); /* doesn't hurt to call this twice */ 1424 1335 dprintk("svc: svc_process dropit\n"); ··· 1446 1351 svc_putnl(resv, 2); 1447 1352 goto sendit; 1448 1353 1354 + err_release_bad_auth: 1355 + if (procp->pc_release) 1356 + procp->pc_release(rqstp); 1449 1357 err_bad_auth: 1450 1358 dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat)); 1451 1359 serv->sv_stats->rpcbadauth++; ··· 1467 1369 1468 1370 err_bad_vers: 1469 1371 svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n", 1470 - vers, prog, progp->pg_name); 1372 + rqstp->rq_vers, rqstp->rq_prog, progp->pg_name); 1471 1373 1472 1374 serv->sv_stats->rpcbadfmt++; 1473 1375 svc_putnl(resv, RPC_PROG_MISMATCH); 1474 - svc_putnl(resv, progp->pg_lovers); 1475 - svc_putnl(resv, progp->pg_hivers); 1376 + svc_putnl(resv, process.mismatch.lovers); 1377 + svc_putnl(resv, process.mismatch.hivers); 1476 1378 goto sendit; 1477 1379 1478 1380 err_bad_proc: 1479 - svc_printk(rqstp, "unknown procedure (%d)\n", proc); 1381 + svc_printk(rqstp, "unknown procedure (%d)\n", rqstp->rq_proc); 1480 1382 1481 1383 serv->sv_stats->rpcbadfmt++; 1482 1384 svc_putnl(resv, RPC_PROC_UNAVAIL);
+11 -6
net/sunrpc/svc_xprt.c
··· 136 136 struct module *owner = xprt->xpt_class->xcl_owner; 137 137 if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) 138 138 svcauth_unix_info_release(xprt); 139 + put_cred(xprt->xpt_cred); 139 140 put_net(xprt->xpt_net); 140 141 /* See comment on corresponding get in xs_setup_bc_tcp(): */ 141 142 if (xprt->xpt_bc_xprt) ··· 253 252 254 253 static int _svc_create_xprt(struct svc_serv *serv, const char *xprt_name, 255 254 struct net *net, const int family, 256 - const unsigned short port, int flags) 255 + const unsigned short port, int flags, 256 + const struct cred *cred) 257 257 { 258 258 struct svc_xprt_class *xcl; 259 259 ··· 275 273 module_put(xcl->xcl_owner); 276 274 return PTR_ERR(newxprt); 277 275 } 276 + newxprt->xpt_cred = get_cred(cred); 278 277 svc_add_new_perm_xprt(serv, newxprt); 279 278 newport = svc_xprt_local_port(newxprt); 280 279 return newport; ··· 289 286 290 287 int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, 291 288 struct net *net, const int family, 292 - const unsigned short port, int flags) 289 + const unsigned short port, int flags, 290 + const struct cred *cred) 293 291 { 294 292 int err; 295 293 296 294 dprintk("svc: creating transport %s[%d]\n", xprt_name, port); 297 - err = _svc_create_xprt(serv, xprt_name, net, family, port, flags); 295 + err = _svc_create_xprt(serv, xprt_name, net, family, port, flags, cred); 298 296 if (err == -EPROTONOSUPPORT) { 299 297 request_module("svc%s", xprt_name); 300 - err = _svc_create_xprt(serv, xprt_name, net, family, port, flags); 298 + err = _svc_create_xprt(serv, xprt_name, net, family, port, flags, cred); 301 299 } 302 300 if (err < 0) 303 301 dprintk("svc: transport %s not found, err %d\n", ··· 786 782 __module_get(xprt->xpt_class->xcl_owner); 787 783 svc_check_conn_limits(xprt->xpt_server); 788 784 newxpt = xprt->xpt_ops->xpo_accept(xprt); 789 - if (newxpt) 785 + if (newxpt) { 786 + newxpt->xpt_cred = get_cred(xprt->xpt_cred); 790 787 svc_add_new_temp_xprt(serv, newxpt); 791 - else 788 + } else 792 789 module_put(xprt->xpt_class->xcl_owner); 793 790 } else if (svc_xprt_reserve_slot(rqstp, xprt)) { 794 791 /* XPT_DATA|XPT_DEFERRED case: */
+9 -6
net/sunrpc/svcauth_unix.c
··· 500 500 rv = get_int(&mesg, &id); 501 501 if (rv) 502 502 return -EINVAL; 503 - uid = make_kuid(&init_user_ns, id); 503 + uid = make_kuid(current_user_ns(), id); 504 504 ug.uid = uid; 505 505 506 506 expiry = get_expiry(&mesg); ··· 522 522 err = -EINVAL; 523 523 if (rv) 524 524 goto out; 525 - kgid = make_kgid(&init_user_ns, gid); 525 + kgid = make_kgid(current_user_ns(), gid); 526 526 if (!gid_valid(kgid)) 527 527 goto out; 528 528 ug.gi->gid[i] = kgid; ··· 555 555 struct cache_detail *cd, 556 556 struct cache_head *h) 557 557 { 558 - struct user_namespace *user_ns = &init_user_ns; 558 + struct user_namespace *user_ns = m->file->f_cred->user_ns; 559 559 struct unix_gid *ug; 560 560 int i; 561 561 int glen; ··· 796 796 struct kvec *argv = &rqstp->rq_arg.head[0]; 797 797 struct kvec *resv = &rqstp->rq_res.head[0]; 798 798 struct svc_cred *cred = &rqstp->rq_cred; 799 + struct user_namespace *userns; 799 800 u32 slen, i; 800 801 int len = argv->iov_len; 801 802 ··· 817 816 * (export-specific) anonymous id by nfsd_setuser. 818 817 * Supplementary gid's will be left alone. 819 818 */ 820 - cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */ 821 - cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */ 819 + userns = (rqstp->rq_xprt && rqstp->rq_xprt->xpt_cred) ? 820 + rqstp->rq_xprt->xpt_cred->user_ns : &init_user_ns; 821 + cred->cr_uid = make_kuid(userns, svc_getnl(argv)); /* uid */ 822 + cred->cr_gid = make_kgid(userns, svc_getnl(argv)); /* gid */ 822 823 slen = svc_getnl(argv); /* gids length */ 823 824 if (slen > UNX_NGROUPS || (len -= (slen + 2)*4) < 0) 824 825 goto badcred; ··· 828 825 if (cred->cr_group_info == NULL) 829 826 return SVC_CLOSE; 830 827 for (i = 0; i < slen; i++) { 831 - kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv)); 828 + kgid_t kgid = make_kgid(userns, svc_getnl(argv)); 832 829 cred->cr_group_info->gid[i] = kgid; 833 830 } 834 831 groups_sort(cred->cr_group_info);
+3 -1
net/sunrpc/svcsock.c
··· 1332 1332 * @fd: file descriptor of the new listener 1333 1333 * @name_return: pointer to buffer to fill in with name of listener 1334 1334 * @len: size of the buffer 1335 + * @cred: credential 1335 1336 * 1336 1337 * Fills in socket name and returns positive length of name if successful. 1337 1338 * Name is terminated with '\n'. On error, returns a negative errno 1338 1339 * value. 1339 1340 */ 1340 1341 int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, 1341 - const size_t len) 1342 + const size_t len, const struct cred *cred) 1342 1343 { 1343 1344 int err = 0; 1344 1345 struct socket *so = sockfd_lookup(fd, &err); ··· 1372 1371 salen = kernel_getsockname(svsk->sk_sock, sin); 1373 1372 if (salen >= 0) 1374 1373 svc_xprt_set_local(&svsk->sk_xprt, sin, salen); 1374 + svsk->sk_xprt.xpt_cred = get_cred(cred); 1375 1375 svc_add_new_perm_xprt(serv, &svsk->sk_xprt); 1376 1376 return svc_one_sock_name(svsk, name_return, len); 1377 1377 out: