Skip to content

Commit

Permalink
Merge tag 'nfsd-5.2' of git://linux-nfs.org/~bfields/linux
Browse files Browse the repository at this point in the history
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
  ...
  • Loading branch information
torvalds committed May 16, 2019
2 parents b06ed1e + 1c73b9d commit 700a800
Show file tree
Hide file tree
Showing 34 changed files with 1,085 additions and 316 deletions.
4 changes: 2 additions & 2 deletions fs/lockd/clntlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4;
int status;

status = lockd_up(nlm_init->net);
status = lockd_up(nlm_init->net, nlm_init->cred);
if (status < 0)
return ERR_PTR(status);

Expand Down Expand Up @@ -241,7 +241,7 @@ reclaimer(void *ptr)
allow_signal(SIGKILL);

down_write(&host->h_rwsem);
lockd_up(net); /* note: this cannot fail as lockd is already running */
lockd_up(net, NULL); /* note: this cannot fail as lockd is already running */

dprintk("lockd: reclaiming locks for host %s\n", host->h_name);

Expand Down
33 changes: 20 additions & 13 deletions fs/lockd/svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,28 +188,31 @@ lockd(void *vrqstp)

static int create_lockd_listener(struct svc_serv *serv, const char *name,
struct net *net, const int family,
const unsigned short port)
const unsigned short port,
const struct cred *cred)
{
struct svc_xprt *xprt;

xprt = svc_find_xprt(serv, name, net, family, 0);
if (xprt == NULL)
return svc_create_xprt(serv, name, net, family, port,
SVC_SOCK_DEFAULTS);
SVC_SOCK_DEFAULTS, cred);
svc_xprt_put(xprt);
return 0;
}

static int create_lockd_family(struct svc_serv *serv, struct net *net,
const int family)
const int family, const struct cred *cred)
{
int err;

err = create_lockd_listener(serv, "udp", net, family, nlm_udpport);
err = create_lockd_listener(serv, "udp", net, family, nlm_udpport,
cred);
if (err < 0)
return err;

return create_lockd_listener(serv, "tcp", net, family, nlm_tcpport);
return create_lockd_listener(serv, "tcp", net, family, nlm_tcpport,
cred);
}

/*
Expand All @@ -222,16 +225,17 @@ static int create_lockd_family(struct svc_serv *serv, struct net *net,
* Returns zero if all listeners are available; otherwise a
* negative errno value is returned.
*/
static int make_socks(struct svc_serv *serv, struct net *net)
static int make_socks(struct svc_serv *serv, struct net *net,
const struct cred *cred)
{
static int warned;
int err;

err = create_lockd_family(serv, net, PF_INET);
err = create_lockd_family(serv, net, PF_INET, cred);
if (err < 0)
goto out_err;

err = create_lockd_family(serv, net, PF_INET6);
err = create_lockd_family(serv, net, PF_INET6, cred);
if (err < 0 && err != -EAFNOSUPPORT)
goto out_err;

Expand All @@ -246,7 +250,8 @@ static int make_socks(struct svc_serv *serv, struct net *net)
return err;
}

static int lockd_up_net(struct svc_serv *serv, struct net *net)
static int lockd_up_net(struct svc_serv *serv, struct net *net,
const struct cred *cred)
{
struct lockd_net *ln = net_generic(net, lockd_net_id);
int error;
Expand All @@ -258,7 +263,7 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net)
if (error)
goto err_bind;

error = make_socks(serv, net);
error = make_socks(serv, net, cred);
if (error < 0)
goto err_bind;
set_grace_period(net);
Expand Down Expand Up @@ -461,7 +466,7 @@ static struct svc_serv *lockd_create_svc(void)
/*
* Bring up the lockd process if it's not already up.
*/
int lockd_up(struct net *net)
int lockd_up(struct net *net, const struct cred *cred)
{
struct svc_serv *serv;
int error;
Expand All @@ -474,7 +479,7 @@ int lockd_up(struct net *net)
goto err_create;
}

error = lockd_up_net(serv, net);
error = lockd_up_net(serv, net, cred);
if (error < 0) {
lockd_unregister_notifiers();
goto err_put;
Expand Down Expand Up @@ -807,5 +812,7 @@ static struct svc_program nlmsvc_program = {
.pg_name = "lockd", /* service name */
.pg_class = "nfsd", /* share authentication with nfsd */
.pg_stats = &nlmsvc_stats, /* stats table */
.pg_authenticate = &lockd_authenticate /* export authentication */
.pg_authenticate = &lockd_authenticate, /* export authentication */
.pg_init_request = svc_generic_init_request,
.pg_rpcbind_set = svc_generic_rpcbind_set,
};
12 changes: 6 additions & 6 deletions fs/locks.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,12 @@ EXPORT_SYMBOL_GPL(locks_alloc_lock);

void locks_release_private(struct file_lock *fl)
{
BUG_ON(waitqueue_active(&fl->fl_wait));
BUG_ON(!list_empty(&fl->fl_list));
BUG_ON(!list_empty(&fl->fl_blocked_requests));
BUG_ON(!list_empty(&fl->fl_blocked_member));
BUG_ON(!hlist_unhashed(&fl->fl_link));

if (fl->fl_ops) {
if (fl->fl_ops->fl_release_private)
fl->fl_ops->fl_release_private(fl);
Expand All @@ -371,12 +377,6 @@ EXPORT_SYMBOL_GPL(locks_release_private);
/* Free a lock which is not in use. */
void locks_free_lock(struct file_lock *fl)
{
BUG_ON(waitqueue_active(&fl->fl_wait));
BUG_ON(!list_empty(&fl->fl_list));
BUG_ON(!list_empty(&fl->fl_blocked_requests));
BUG_ON(!list_empty(&fl->fl_blocked_member));
BUG_ON(!hlist_unhashed(&fl->fl_link));

locks_release_private(fl);
kmem_cache_free(filelock_cache, fl);
}
Expand Down
9 changes: 7 additions & 2 deletions fs/nfs/callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,22 @@ static struct svc_program nfs4_callback_program;

static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net)
{
const struct cred *cred = current_cred();
int ret;
struct nfs_net *nn = net_generic(net, nfs_net_id);

ret = svc_create_xprt(serv, "tcp", net, PF_INET,
nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
cred);
if (ret <= 0)
goto out_err;
nn->nfs_callback_tcpport = ret;
dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
nn->nfs_callback_tcpport, PF_INET, net->ns.inum);

ret = svc_create_xprt(serv, "tcp", net, PF_INET6,
nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
cred);
if (ret > 0) {
nn->nfs_callback_tcpport6 = ret;
dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
Expand Down Expand Up @@ -457,4 +460,6 @@ static struct svc_program nfs4_callback_program = {
.pg_class = "nfs", /* authentication class */
.pg_stats = &nfs4_callback_stats,
.pg_authenticate = nfs_callback_authenticate,
.pg_init_request = svc_generic_init_request,
.pg_rpcbind_set = svc_generic_rpcbind_set,
};
2 changes: 1 addition & 1 deletion fs/nfs/callback_xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp)

out_invalidcred:
pr_warn_ratelimited("NFS: NFSv4 callback contains invalid cred\n");
return rpc_autherr_badcred;
return svc_return_autherr(rqstp, rpc_autherr_badcred);
}

/*
Expand Down
1 change: 1 addition & 0 deletions fs/nfs/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@ static int nfs_start_lockd(struct nfs_server *server)
1 : 0,
.net = clp->cl_net,
.nlmclnt_ops = clp->cl_nfs_mod->rpc_ops->nlmclnt_ops,
.cred = current_cred(),
};

if (nlm_init.nfs_version > 3)
Expand Down
18 changes: 10 additions & 8 deletions fs/nfsd/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,13 +570,13 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
err = get_int(&mesg, &an_int);
if (err)
goto out3;
exp.ex_anon_uid= make_kuid(&init_user_ns, an_int);
exp.ex_anon_uid= make_kuid(current_user_ns(), an_int);

/* anon gid */
err = get_int(&mesg, &an_int);
if (err)
goto out3;
exp.ex_anon_gid= make_kgid(&init_user_ns, an_int);
exp.ex_anon_gid= make_kgid(current_user_ns(), an_int);

/* fsid */
err = get_int(&mesg, &an_int);
Expand Down Expand Up @@ -1170,15 +1170,17 @@ static void show_secinfo(struct seq_file *m, struct svc_export *exp)
static void exp_flags(struct seq_file *m, int flag, int fsid,
kuid_t anonu, kgid_t anong, struct nfsd4_fs_locations *fsloc)
{
struct user_namespace *userns = m->file->f_cred->user_ns;

show_expflags(m, flag, NFSEXP_ALLFLAGS);
if (flag & NFSEXP_FSID)
seq_printf(m, ",fsid=%d", fsid);
if (!uid_eq(anonu, make_kuid(&init_user_ns, (uid_t)-2)) &&
!uid_eq(anonu, make_kuid(&init_user_ns, 0x10000-2)))
seq_printf(m, ",anonuid=%u", from_kuid(&init_user_ns, anonu));
if (!gid_eq(anong, make_kgid(&init_user_ns, (gid_t)-2)) &&
!gid_eq(anong, make_kgid(&init_user_ns, 0x10000-2)))
seq_printf(m, ",anongid=%u", from_kgid(&init_user_ns, anong));
if (!uid_eq(anonu, make_kuid(userns, (uid_t)-2)) &&
!uid_eq(anonu, make_kuid(userns, 0x10000-2)))
seq_printf(m, ",anonuid=%u", from_kuid_munged(userns, anonu));
if (!gid_eq(anong, make_kgid(userns, (gid_t)-2)) &&
!gid_eq(anong, make_kgid(userns, 0x10000-2)))
seq_printf(m, ",anongid=%u", from_kgid_munged(userns, anong));
if (fsloc && fsloc->locations_count > 0) {
char *loctype = (fsloc->migrated) ? "refer" : "replicas";
int i;
Expand Down
11 changes: 11 additions & 0 deletions fs/nfsd/netns.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ struct nfsd_net {
time_t nfsd4_grace;
bool somebody_reclaimed;

bool track_reclaim_completes;
atomic_t nr_reclaim_complete;

bool nfsd_net_up;
bool lockd_up;

Expand Down Expand Up @@ -131,10 +134,18 @@ struct nfsd_net {
u32 s2s_cp_cl_id;
struct idr s2s_cp_stateids;
spinlock_t s2s_cp_lock;

/*
* Version information
*/
bool *nfsd_versions;
bool *nfsd4_minorversions;
};

/* Simple check to find out if a given net was properly initialized */
#define nfsd_netns_ready(nn) ((nn)->sessionid_hashtbl)

extern void nfsd_netns_free_versions(struct nfsd_net *nn);

extern unsigned int nfsd_net_id;
#endif /* __NFSD_NETNS_H__ */
21 changes: 11 additions & 10 deletions fs/nfsd/nfs3xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ decode_filename(__be32 *p, char **namp, unsigned int *lenp)
}

static __be32 *
decode_sattr3(__be32 *p, struct iattr *iap)
decode_sattr3(__be32 *p, struct iattr *iap, struct user_namespace *userns)
{
u32 tmp;

Expand All @@ -107,12 +107,12 @@ decode_sattr3(__be32 *p, struct iattr *iap)
iap->ia_mode = ntohl(*p++);
}
if (*p++) {
iap->ia_uid = make_kuid(&init_user_ns, ntohl(*p++));
iap->ia_uid = make_kuid(userns, ntohl(*p++));
if (uid_valid(iap->ia_uid))
iap->ia_valid |= ATTR_UID;
}
if (*p++) {
iap->ia_gid = make_kgid(&init_user_ns, ntohl(*p++));
iap->ia_gid = make_kgid(userns, ntohl(*p++));
if (gid_valid(iap->ia_gid))
iap->ia_valid |= ATTR_GID;
}
Expand Down Expand Up @@ -165,12 +165,13 @@ static __be32 *
encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
struct kstat *stat)
{
struct user_namespace *userns = nfsd_user_namespace(rqstp);
struct timespec ts;
*p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
*p++ = htonl((u32) (stat->mode & S_IALLUGO));
*p++ = htonl((u32) stat->nlink);
*p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid));
*p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid));
*p++ = htonl((u32) from_kuid_munged(userns, stat->uid));
*p++ = htonl((u32) from_kgid_munged(userns, stat->gid));
if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) {
p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
} else {
Expand Down Expand Up @@ -325,7 +326,7 @@ nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
p = decode_fh(p, &args->fh);
if (!p)
return 0;
p = decode_sattr3(p, &args->attrs);
p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));

if ((args->check_guard = ntohl(*p++)) != 0) {
struct timespec time;
Expand Down Expand Up @@ -455,7 +456,7 @@ nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
switch (args->createmode = ntohl(*p++)) {
case NFS3_CREATE_UNCHECKED:
case NFS3_CREATE_GUARDED:
p = decode_sattr3(p, &args->attrs);
p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
break;
case NFS3_CREATE_EXCLUSIVE:
args->verf = p;
Expand All @@ -476,7 +477,7 @@ nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p)
if (!(p = decode_fh(p, &args->fh)) ||
!(p = decode_filename(p, &args->name, &args->len)))
return 0;
p = decode_sattr3(p, &args->attrs);
p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));

return xdr_argsize_check(rqstp, p);
}
Expand All @@ -491,7 +492,7 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
if (!(p = decode_fh(p, &args->ffh)) ||
!(p = decode_filename(p, &args->fname, &args->flen)))
return 0;
p = decode_sattr3(p, &args->attrs);
p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));

args->tlen = ntohl(*p++);

Expand Down Expand Up @@ -519,7 +520,7 @@ nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p)

if (args->ftype == NF3BLK || args->ftype == NF3CHR
|| args->ftype == NF3SOCK || args->ftype == NF3FIFO)
p = decode_sattr3(p, &args->attrs);
p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));

if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
args->major = ntohl(*p++);
Expand Down
9 changes: 5 additions & 4 deletions fs/nfsd/nfs4callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -1123,10 +1123,11 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
rpc_restart_call_prepare(task);
return;
case 1:
break;
case -1:
/* Network partition? */
nfsd4_mark_cb_down(clp, task->tk_status);
switch (task->tk_status) {
case -EIO:
case -ETIMEDOUT:
nfsd4_mark_cb_down(clp, task->tk_status);
}
break;
default:
BUG();
Expand Down
Loading

0 comments on commit 700a800

Please sign in to comment.