Skip to content

Commit de37033

Browse files
authored
NAS-132233 / 24.10.1 / merge upstream NFS-related fixes
* nfsd: fix delegation_blocked() to block correctly for at least 30 seconds * nfsd: return -EINVAL when namelen is 0 * nfsd: fix refcount leak when file is unhashed after being found * SUNRPC: Fix a race to wake a sync task * NFSv4: Add missing rescheduling points in nfs_client_return_marked_delegations * nfs: fix memory leak in error path of nfs4_do_reclaim * SUNRPC: Fix integer overflow in decode_rc_list() * NFSv4: Prevent NULL-pointer dereference in nfs42_complete_copies() * NFS: Avoid unnecessary rescanning of the per-server delegation list * NFSD: Fix NFSv4's PUTPUBFH operation * NFSD: simplify error paths in nfsd_svc()
2 parents ff82817 + e3191a7 commit de37033

File tree

13 files changed

+34
-34
lines changed

13 files changed

+34
-34
lines changed

fs/nfs/callback_xdr.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,8 @@ static __be32 decode_rc_list(struct xdr_stream *xdr,
372372

373373
rc_list->rcl_nrefcalls = ntohl(*p++);
374374
if (rc_list->rcl_nrefcalls) {
375+
if (unlikely(rc_list->rcl_nrefcalls > xdr->buf->len))
376+
goto out;
375377
p = xdr_inline_decode(xdr,
376378
rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t));
377379
if (unlikely(p == NULL))

fs/nfs/client.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,7 @@ struct nfs_server *nfs_alloc_server(void)
987987
INIT_LIST_HEAD(&server->layouts);
988988
INIT_LIST_HEAD(&server->state_owners_lru);
989989
INIT_LIST_HEAD(&server->ss_copies);
990+
INIT_LIST_HEAD(&server->ss_src_copies);
990991

991992
atomic_set(&server->active, 0);
992993

fs/nfs/delegation.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,9 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server,
627627
prev = delegation;
628628
continue;
629629
}
630+
inode = nfs_delegation_grab_inode(delegation);
631+
if (inode == NULL)
632+
continue;
630633

631634
if (prev) {
632635
struct inode *tmp = nfs_delegation_grab_inode(prev);
@@ -637,12 +640,6 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server,
637640
}
638641
}
639642

640-
inode = nfs_delegation_grab_inode(delegation);
641-
if (inode == NULL) {
642-
rcu_read_unlock();
643-
iput(to_put);
644-
goto restart;
645-
}
646643
delegation = nfs_start_delegation_return_locked(NFS_I(inode));
647644
rcu_read_unlock();
648645

@@ -1164,7 +1161,6 @@ static int nfs_server_reap_unclaimed_delegations(struct nfs_server *server,
11641161
struct inode *inode;
11651162
restart:
11661163
rcu_read_lock();
1167-
restart_locked:
11681164
list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
11691165
if (test_bit(NFS_DELEGATION_INODE_FREEING,
11701166
&delegation->flags) ||
@@ -1175,7 +1171,7 @@ static int nfs_server_reap_unclaimed_delegations(struct nfs_server *server,
11751171
continue;
11761172
inode = nfs_delegation_grab_inode(delegation);
11771173
if (inode == NULL)
1178-
goto restart_locked;
1174+
continue;
11791175
delegation = nfs_start_delegation_return_locked(NFS_I(inode));
11801176
rcu_read_unlock();
11811177
if (delegation != NULL) {
@@ -1296,7 +1292,6 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server,
12961292
nfs4_stateid stateid;
12971293
restart:
12981294
rcu_read_lock();
1299-
restart_locked:
13001295
list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
13011296
if (test_bit(NFS_DELEGATION_INODE_FREEING,
13021297
&delegation->flags) ||
@@ -1307,7 +1302,7 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server,
13071302
continue;
13081303
inode = nfs_delegation_grab_inode(delegation);
13091304
if (inode == NULL)
1310-
goto restart_locked;
1305+
continue;
13111306
spin_lock(&delegation->lock);
13121307
cred = get_cred_rcu(delegation->cred);
13131308
nfs4_stateid_copy(&stateid, &delegation->stateid);

fs/nfs/nfs42proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ static int handle_async_copy(struct nfs42_copy_res *res,
218218

219219
if (dst_server != src_server) {
220220
spin_lock(&src_server->nfs_client->cl_lock);
221-
list_add_tail(&copy->src_copies, &src_server->ss_copies);
221+
list_add_tail(&copy->src_copies, &src_server->ss_src_copies);
222222
spin_unlock(&src_server->nfs_client->cl_lock);
223223
}
224224

fs/nfs/nfs4state.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1597,7 +1597,7 @@ static void nfs42_complete_copies(struct nfs4_state_owner *sp, struct nfs4_state
15971597
complete(&copy->completion);
15981598
}
15991599
}
1600-
list_for_each_entry(copy, &sp->so_server->ss_copies, src_copies) {
1600+
list_for_each_entry(copy, &sp->so_server->ss_src_copies, src_copies) {
16011601
if ((test_bit(NFS_CLNT_SRC_SSC_COPY_STATE, &state->flags) &&
16021602
!nfs4_stateid_match_other(&state->stateid,
16031603
&copy->parent_src_state->stateid)))
@@ -1957,6 +1957,7 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov
19571957
set_bit(ops->owner_flag_bit, &sp->so_flags);
19581958
nfs4_put_state_owner(sp);
19591959
status = nfs4_recovery_handle_error(clp, status);
1960+
nfs4_free_state_owners(&freeme);
19601961
return (status != 0) ? status : -EAGAIN;
19611962
}
19621963

fs/nfs/super.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include <linux/vfs.h>
4848
#include <linux/inet.h>
4949
#include <linux/in6.h>
50+
#include <linux/sched.h>
5051
#include <linux/slab.h>
5152
#include <net/ipv6.h>
5253
#include <linux/netdevice.h>
@@ -223,6 +224,7 @@ static int __nfs_list_for_each_server(struct list_head *head,
223224
ret = fn(server, data);
224225
if (ret)
225226
goto out;
227+
cond_resched();
226228
rcu_read_lock();
227229
}
228230
rcu_read_unlock();

fs/nfsd/filecache.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,7 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
10561056
status = nfserr_jukebox;
10571057
goto construction_err;
10581058
}
1059+
nfsd_file_put(nf);
10591060
open_retry = false;
10601061
fh_put(fhp);
10611062
goto retry;

fs/nfsd/nfs4recover.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,10 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,
806806
ci = &cmsg->cm_u.cm_clntinfo;
807807
if (get_user(namelen, &ci->cc_name.cn_len))
808808
return -EFAULT;
809+
if (!namelen) {
810+
dprintk("%s: namelen should not be zero", __func__);
811+
return -EINVAL;
812+
}
809813
name.data = memdup_user(&ci->cc_name.cn_id, namelen);
810814
if (IS_ERR(name.data))
811815
return PTR_ERR(name.data);
@@ -828,6 +832,10 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,
828832
cnm = &cmsg->cm_u.cm_name;
829833
if (get_user(namelen, &cnm->cn_len))
830834
return -EFAULT;
835+
if (!namelen) {
836+
dprintk("%s: namelen should not be zero", __func__);
837+
return -EINVAL;
838+
}
831839
name.data = memdup_user(&cnm->cn_id, namelen);
832840
if (IS_ERR(name.data))
833841
return PTR_ERR(name.data);

fs/nfsd/nfs4state.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,8 @@ static void nfs4_free_deleg(struct nfs4_stid *stid)
10871087
* When a delegation is recalled, the filehandle is stored in the "new"
10881088
* filter.
10891089
* Every 30 seconds we swap the filters and clear the "new" one,
1090-
* unless both are empty of course.
1090+
* unless both are empty of course. This results in delegations for a
1091+
* given filehandle being blocked for between 30 and 60 seconds.
10911092
*
10921093
* Each filter is 256 bits. We hash the filehandle to 32bit and use the
10931094
* low 3 bytes as hash-table indices.
@@ -1116,9 +1117,9 @@ static int delegation_blocked(struct knfsd_fh *fh)
11161117
if (ktime_get_seconds() - bd->swap_time > 30) {
11171118
bd->entries -= bd->old_entries;
11181119
bd->old_entries = bd->entries;
1120+
bd->new = 1-bd->new;
11191121
memset(bd->set[bd->new], 0,
11201122
sizeof(bd->set[0]));
1121-
bd->new = 1-bd->new;
11221123
bd->swap_time = ktime_get_seconds();
11231124
}
11241125
spin_unlock(&blocked_delegations_lock);

fs/nfsd/nfs4xdr.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,14 +1287,6 @@ nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
12871287
return nfs_ok;
12881288
}
12891289

1290-
static __be32
1291-
nfsd4_decode_putpubfh(struct nfsd4_compoundargs *argp, union nfsd4_op_u *p)
1292-
{
1293-
if (argp->minorversion == 0)
1294-
return nfs_ok;
1295-
return nfserr_notsupp;
1296-
}
1297-
12981290
static __be32
12991291
nfsd4_decode_read(struct nfsd4_compoundargs *argp, union nfsd4_op_u *u)
13001292
{
@@ -2387,7 +2379,7 @@ static const nfsd4_dec nfsd4_dec_ops[] = {
23872379
[OP_OPEN_CONFIRM] = nfsd4_decode_open_confirm,
23882380
[OP_OPEN_DOWNGRADE] = nfsd4_decode_open_downgrade,
23892381
[OP_PUTFH] = nfsd4_decode_putfh,
2390-
[OP_PUTPUBFH] = nfsd4_decode_putpubfh,
2382+
[OP_PUTPUBFH] = nfsd4_decode_noop,
23912383
[OP_PUTROOTFH] = nfsd4_decode_noop,
23922384
[OP_READ] = nfsd4_decode_read,
23932385
[OP_READDIR] = nfsd4_decode_readdir,

0 commit comments

Comments
 (0)