Skip to content

Commit 53e760d

Browse files
committed
Merge tag 'nfsd-6.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
Pull nfsd fixes from Chuck Lever: - A correctness fix for delegated timestamps - Address an NFSD shutdown hang when LOCALIO is in use - Prevent a remotely exploitable crasher when TLS is in use * tag 'nfsd-6.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: sunrpc: fix handling of server side tls alerts nfsd: avoid ref leak in nfsd_open_local_fh() nfsd: don't set the ctime on delegated atime updates
2 parents 8f5ae30 + bee47cb commit 53e760d

File tree

3 files changed

+47
-11
lines changed

3 files changed

+47
-11
lines changed

fs/nfsd/localio.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,11 @@ nfsd_open_local_fh(struct net *net, struct auth_domain *dom,
103103
if (nfsd_file_get(new) == NULL)
104104
goto again;
105105
/*
106-
* Drop the ref we were going to install and the
107-
* one we were going to return.
106+
* Drop the ref we were going to install (both file and
107+
* net) and the one we were going to return (only file).
108108
*/
109109
nfsd_file_put(localio);
110+
nfsd_net_put(net);
110111
nfsd_file_put(localio);
111112
localio = new;
112113
}

fs/nfsd/vfs.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,15 @@ static int __nfsd_setattr(struct dentry *dentry, struct iattr *iap)
470470
if (!iap->ia_valid)
471471
return 0;
472472

473-
iap->ia_valid |= ATTR_CTIME;
473+
/*
474+
* If ATTR_DELEG is set, then this is an update from a client that
475+
* holds a delegation. If this is an update for only the atime, the
476+
* ctime should not be changed. If the update contains the mtime
477+
* too, then ATTR_CTIME should already be set.
478+
*/
479+
if (!(iap->ia_valid & ATTR_DELEG))
480+
iap->ia_valid |= ATTR_CTIME;
481+
474482
return notify_change(&nop_mnt_idmap, dentry, iap, NULL);
475483
}
476484

net/sunrpc/svcsock.c

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -257,20 +257,47 @@ svc_tcp_sock_process_cmsg(struct socket *sock, struct msghdr *msg,
257257
}
258258

259259
static int
260-
svc_tcp_sock_recv_cmsg(struct svc_sock *svsk, struct msghdr *msg)
260+
svc_tcp_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags)
261261
{
262262
union {
263263
struct cmsghdr cmsg;
264264
u8 buf[CMSG_SPACE(sizeof(u8))];
265265
} u;
266-
struct socket *sock = svsk->sk_sock;
266+
u8 alert[2];
267+
struct kvec alert_kvec = {
268+
.iov_base = alert,
269+
.iov_len = sizeof(alert),
270+
};
271+
struct msghdr msg = {
272+
.msg_flags = *msg_flags,
273+
.msg_control = &u,
274+
.msg_controllen = sizeof(u),
275+
};
276+
int ret;
277+
278+
iov_iter_kvec(&msg.msg_iter, ITER_DEST, &alert_kvec, 1,
279+
alert_kvec.iov_len);
280+
ret = sock_recvmsg(sock, &msg, MSG_DONTWAIT);
281+
if (ret > 0 &&
282+
tls_get_record_type(sock->sk, &u.cmsg) == TLS_RECORD_TYPE_ALERT) {
283+
iov_iter_revert(&msg.msg_iter, ret);
284+
ret = svc_tcp_sock_process_cmsg(sock, &msg, &u.cmsg, -EAGAIN);
285+
}
286+
return ret;
287+
}
288+
289+
static int
290+
svc_tcp_sock_recvmsg(struct svc_sock *svsk, struct msghdr *msg)
291+
{
267292
int ret;
293+
struct socket *sock = svsk->sk_sock;
268294

269-
msg->msg_control = &u;
270-
msg->msg_controllen = sizeof(u);
271295
ret = sock_recvmsg(sock, msg, MSG_DONTWAIT);
272-
if (unlikely(msg->msg_controllen != sizeof(u)))
273-
ret = svc_tcp_sock_process_cmsg(sock, msg, &u.cmsg, ret);
296+
if (msg->msg_flags & MSG_CTRUNC) {
297+
msg->msg_flags &= ~(MSG_CTRUNC | MSG_EOR);
298+
if (ret == 0 || ret == -EIO)
299+
ret = svc_tcp_sock_recv_cmsg(sock, &msg->msg_flags);
300+
}
274301
return ret;
275302
}
276303

@@ -321,7 +348,7 @@ static ssize_t svc_tcp_read_msg(struct svc_rqst *rqstp, size_t buflen,
321348
iov_iter_advance(&msg.msg_iter, seek);
322349
buflen -= seek;
323350
}
324-
len = svc_tcp_sock_recv_cmsg(svsk, &msg);
351+
len = svc_tcp_sock_recvmsg(svsk, &msg);
325352
if (len > 0)
326353
svc_flush_bvec(bvec, len, seek);
327354

@@ -1018,7 +1045,7 @@ static ssize_t svc_tcp_read_marker(struct svc_sock *svsk,
10181045
iov.iov_base = ((char *)&svsk->sk_marker) + svsk->sk_tcplen;
10191046
iov.iov_len = want;
10201047
iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, want);
1021-
len = svc_tcp_sock_recv_cmsg(svsk, &msg);
1048+
len = svc_tcp_sock_recvmsg(svsk, &msg);
10221049
if (len < 0)
10231050
return len;
10241051
svsk->sk_tcplen += len;

0 commit comments

Comments
 (0)