Commit eb3f4b74 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull nfsd fixes from Chuck Lever:
 "Regressions:

   - Tighten bounds checking for sunrpc cache hash tables

   - Don't report key material in the ftrace log

  Stable fix:

   - Fix lockd's implementation of the NLM TEST procedure"

* tag 'nfsd-7.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
  lockd: fix TEST handling when not all permissions are available.
  NFSD: Report whether fh_key was actually updated
  sunrpc: prevent out-of-bounds read in __cache_seq_start()
parents e909cedf 0b474240
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -332,7 +332,7 @@ int nlmsvc_dispatch(struct svc_rqst *rqstp);
 * File handling for the server personality
 */
__be32		  nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
					struct nlm_lock *);
				  struct nlm_lock *, int);
void		  nlm_release_file(struct nlm_file *);
void		  nlmsvc_put_lockowner(struct nlm_lockowner *);
void		  nlmsvc_release_lockowner(struct nlm_lock *);
+7 −2
Original line number Diff line number Diff line
@@ -146,8 +146,11 @@ nlm4svc_lookup_file(struct svc_rqst *rqstp, struct nlm_host *host,
		    struct nlm_lock *lock, struct nlm_file **filp,
		    struct nlm4_lock *xdr_lock, unsigned char type)
{
	bool is_test = (rqstp->rq_proc == NLMPROC4_TEST ||
			rqstp->rq_proc == NLMPROC4_TEST_MSG);
	struct file_lock *fl = &lock->fl;
	struct nlm_file *file = NULL;
	int mode;
	__be32 error;

	if (xdr_lock->fh.len > NFS_MAXFHSIZE)
@@ -170,7 +173,8 @@ nlm4svc_lookup_file(struct svc_rqst *rqstp, struct nlm_host *host,
	fl->c.flc_type = type;
	lockd_set_file_lock_range4(fl, lock->lock_start, lock->lock_len);

	error = nlm_lookup_file(rqstp, &file, lock);
	mode = is_test ? O_RDWR : lock_to_openmode(fl);
	error = nlm_lookup_file(rqstp, &file, lock, mode);
	switch (error) {
	case nlm_granted:
		break;
@@ -184,7 +188,8 @@ nlm4svc_lookup_file(struct svc_rqst *rqstp, struct nlm_host *host,
	*filp = file;

	fl->c.flc_flags = FL_POSIX;
	fl->c.flc_file = file->f_file[lock_to_openmode(fl)];
	fl->c.flc_file = is_test ? nlmsvc_file_file(file)
				 : file->f_file[mode];
	fl->c.flc_pid = current->tgid;
	fl->fl_lmops = &nlmsvc_lock_operations;
	nlmsvc_locks_init_private(fl, host, (pid_t)lock->svid);
+1 −3
Original line number Diff line number Diff line
@@ -613,7 +613,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
		struct nlm_lock *conflock)
{
	int			error;
	int			mode;
	__be32			ret;

	dprintk("lockd: nlmsvc_testlock(%s/%llu, ty=%d, %Ld-%Ld)\n",
@@ -631,14 +630,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
		goto out;
	}

	mode = lock_to_openmode(&lock->fl);
	locks_init_lock(&conflock->fl);
	/* vfs_test_lock only uses start, end, and owner, but tests flc_file */
	conflock->fl.c.flc_file = lock->fl.c.flc_file;
	conflock->fl.fl_start = lock->fl.fl_start;
	conflock->fl.fl_end = lock->fl.fl_end;
	conflock->fl.c.flc_owner = lock->fl.c.flc_owner;
	error = vfs_test_lock(file->f_file[mode], &conflock->fl);
	error = vfs_test_lock(lock->fl.c.flc_file, &conflock->fl);
	if (error) {
		ret = nlm_lck_denied_nolocks;
		goto out;
+12 −3
Original line number Diff line number Diff line
@@ -68,6 +68,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
	struct nlm_host		*host = NULL;
	struct nlm_file		*file = NULL;
	struct nlm_lock		*lock = &argp->lock;
	bool			is_test = (rqstp->rq_proc == NLMPROC_TEST ||
					   rqstp->rq_proc == NLMPROC_TEST_MSG);
	int			mode;
	__be32			error = 0;

@@ -83,14 +85,21 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,

	/* Obtain file pointer. Not used by FREE_ALL call. */
	if (filp != NULL) {
		error = cast_status(nlm_lookup_file(rqstp, &file, lock));
		mode = lock_to_openmode(&lock->fl);

		if (is_test)
			mode = O_RDWR;

		error = cast_status(nlm_lookup_file(rqstp, &file, lock, mode));
		if (error != 0)
			goto no_locks;
		*filp = file;

		/* Set up the missing parts of the file_lock structure */
		mode = lock_to_openmode(&lock->fl);
		lock->fl.c.flc_flags = FL_POSIX;
		if (is_test)
			lock->fl.c.flc_file = nlmsvc_file_file(file);
		else
			lock->fl.c.flc_file = file->f_file[mode];
		lock->fl.c.flc_pid = current->tgid;
		lock->fl.fl_lmops = &nlmsvc_lock_operations;
+21 −10
Original line number Diff line number Diff line
@@ -83,23 +83,36 @@ int lock_to_openmode(struct file_lock *lock)
 *
 * We have to make sure we have the right credential to open
 * the file.
 *
 * @mode is O_RDONLY, O_WRONLY, or O_RDWR. O_RDWR means success
 * is achieved with EITHER O_RDONLY or O_WRONLY; it does not
 * require both.
 */
static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
			   struct nlm_file *file, int mode)
{
	struct file **fp = &file->f_file[mode];
	__be32 nlmerr = nlm_granted;
	__be32 nlmerr = nlm__int__failed;
	__be32 deferred = 0;
	int error;
	int m;

	for (m = O_RDONLY; m <= O_WRONLY; m++) {
		struct file **fp = &file->f_file[m];

		if (mode != O_RDWR && mode != m)
			continue;
		if (*fp)
		return nlmerr;
			return nlm_granted;

		error = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, m);
		if (!error)
			return nlm_granted;

	error = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, mode);
	if (error) {
		dprintk("lockd: open failed (errno %d)\n", error);
		switch (error) {
		case -EWOULDBLOCK:
			nlmerr = nlm__int__drop_reply;
			deferred = nlmerr;
			break;
		case -ESTALE:
			nlmerr = nlm__int__stale_fh;
@@ -110,7 +123,7 @@ static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
		}
	}

	return nlmerr;
	return deferred ? deferred : nlmerr;
}

/*
@@ -119,17 +132,15 @@ static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
 */
__be32
nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
					struct nlm_lock *lock)
		struct nlm_lock *lock, int mode)
{
	struct nlm_file	*file;
	unsigned int	hash;
	__be32		nfserr;
	int		mode;

	nlm_debug_print_fh("nlm_lookup_file", &lock->fh);

	hash = file_hash(&lock->fh);
	mode = lock_to_openmode(&lock->fl);

	/* Lock file table */
	mutex_lock(&nlm_file_mutex);
Loading