Skip to content

Commit

Permalink
Merge tag 'nfs-for-6.1-2' of git://git.linux-nfs.org/projects/anna/li…
Browse files Browse the repository at this point in the history
…nux-nfs

Pull NFS client bugfixes from Anna Schumaker:

 - Fix some coccicheck warnings

 - Avoid memcpy() run-time warning

 - Fix up various state reclaim / RECLAIM_COMPLETE errors

 - Fix a null pointer dereference in sysfs

 - Fix LOCK races

 - Fix gss_unwrap_resp_integ() crasher

 - Fix zero length clones

 - Fix memleak when allocate slot fails

* tag 'nfs-for-6.1-2' of git://git.linux-nfs.org/projects/anna/linux-nfs:
  nfs4: Fix kmemleak when allocate slot failed
  NFSv4.2: Fixup CLONE dest file size for zero-length count
  SUNRPC: Fix crasher in gss_unwrap_resp_integ()
  NFSv4: Retry LOCK on OLD_STATEID during delegation return
  SUNRPC: Fix null-ptr-deref when xps sysfs alloc failed
  NFSv4.1: We must always send RECLAIM_COMPLETE after a reboot
  NFSv4.1: Handle RECLAIM_COMPLETE trunking errors
  NFSv4: Fix a potential state reclaim deadlock
  NFS: Avoid memcpy() run-time warning for struct sockaddr overflows
  nfs: Remove redundant null checks before kfree
  • Loading branch information
Linus Torvalds committed Nov 2, 2022
2 parents ae13366 + 7e84367 commit 31fc92f
Show file tree
Hide file tree
Showing 20 changed files with 91 additions and 78 deletions.
4 changes: 2 additions & 2 deletions fs/nfs/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ EXPORT_SYMBOL_GPL(nfs_put_client);
static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data)
{
struct nfs_client *clp;
const struct sockaddr *sap = data->addr;
const struct sockaddr *sap = (struct sockaddr *)data->addr;
struct nfs_net *nn = net_generic(data->net, nfs_net_id);
int error;

Expand Down Expand Up @@ -666,7 +666,7 @@ static int nfs_init_server(struct nfs_server *server,
struct rpc_timeout timeparms;
struct nfs_client_initdata cl_init = {
.hostname = ctx->nfs_server.hostname,
.addr = (const struct sockaddr *)&ctx->nfs_server.address,
.addr = &ctx->nfs_server._address,
.addrlen = ctx->nfs_server.addrlen,
.nfs_mod = ctx->nfs_mod,
.proto = ctx->nfs_server.protocol,
Expand Down
36 changes: 17 additions & 19 deletions fs/nfs/delegation.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,7 @@ static int nfs_delegation_claim_opens(struct inode *inode,
*
*/
void nfs_inode_reclaim_delegation(struct inode *inode, const struct cred *cred,
fmode_t type,
const nfs4_stateid *stateid,
fmode_t type, const nfs4_stateid *stateid,
unsigned long pagemod_limit)
{
struct nfs_delegation *delegation;
Expand All @@ -239,25 +238,24 @@ void nfs_inode_reclaim_delegation(struct inode *inode, const struct cred *cred,
delegation = rcu_dereference(NFS_I(inode)->delegation);
if (delegation != NULL) {
spin_lock(&delegation->lock);
if (nfs4_is_valid_delegation(delegation, 0)) {
nfs4_stateid_copy(&delegation->stateid, stateid);
delegation->type = type;
delegation->pagemod_limit = pagemod_limit;
oldcred = delegation->cred;
delegation->cred = get_cred(cred);
clear_bit(NFS_DELEGATION_NEED_RECLAIM,
&delegation->flags);
spin_unlock(&delegation->lock);
rcu_read_unlock();
put_cred(oldcred);
trace_nfs4_reclaim_delegation(inode, type);
return;
}
/* We appear to have raced with a delegation return. */
nfs4_stateid_copy(&delegation->stateid, stateid);
delegation->type = type;
delegation->pagemod_limit = pagemod_limit;
oldcred = delegation->cred;
delegation->cred = get_cred(cred);
clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
if (test_and_clear_bit(NFS_DELEGATION_REVOKED,
&delegation->flags))
atomic_long_inc(&nfs_active_delegations);
spin_unlock(&delegation->lock);
rcu_read_unlock();
put_cred(oldcred);
trace_nfs4_reclaim_delegation(inode, type);
} else {
rcu_read_unlock();
nfs_inode_set_delegation(inode, cred, type, stateid,
pagemod_limit);
}
rcu_read_unlock();
nfs_inode_set_delegation(inode, cred, type, stateid, pagemod_limit);
}

static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
Expand Down
5 changes: 2 additions & 3 deletions fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -2489,9 +2489,8 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
spin_unlock(&dentry->d_lock);
goto out;
}
if (dentry->d_fsdata)
/* old devname */
kfree(dentry->d_fsdata);
/* old devname */
kfree(dentry->d_fsdata);
dentry->d_fsdata = NFS_FSDATA_BLOCKED;

spin_unlock(&dentry->d_lock);
Expand Down
7 changes: 4 additions & 3 deletions fs/nfs/dns_resolve.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
#include "dns_resolve.h"

ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,
struct sockaddr *sa, size_t salen)
struct sockaddr_storage *ss, size_t salen)
{
struct sockaddr *sa = (struct sockaddr *)ss;
ssize_t ret;
char *ip_addr = NULL;
int ip_len;
Expand Down Expand Up @@ -341,7 +342,7 @@ static int do_cache_lookup_wait(struct cache_detail *cd,
}

ssize_t nfs_dns_resolve_name(struct net *net, char *name,
size_t namelen, struct sockaddr *sa, size_t salen)
size_t namelen, struct sockaddr_storage *ss, size_t salen)
{
struct nfs_dns_ent key = {
.hostname = name,
Expand All @@ -354,7 +355,7 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name,
ret = do_cache_lookup_wait(nn->nfs_dns_resolve, &key, &item);
if (ret == 0) {
if (salen >= item->addrlen) {
memcpy(sa, &item->addr, item->addrlen);
memcpy(ss, &item->addr, item->addrlen);
ret = item->addrlen;
} else
ret = -EOVERFLOW;
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/dns_resolve.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ extern void nfs_dns_resolver_cache_destroy(struct net *net);
#endif

extern ssize_t nfs_dns_resolve_name(struct net *net, char *name,
size_t namelen, struct sockaddr *sa, size_t salen);
size_t namelen, struct sockaddr_storage *sa, size_t salen);

#endif
14 changes: 7 additions & 7 deletions fs/nfs/fs_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,9 @@ static const struct constant_table nfs_secflavor_tokens[] = {
* Address family must be initialized, and address must not be
* the ANY address for that family.
*/
static int nfs_verify_server_address(struct sockaddr *addr)
static int nfs_verify_server_address(struct sockaddr_storage *addr)
{
switch (addr->sa_family) {
switch (addr->ss_family) {
case AF_INET: {
struct sockaddr_in *sa = (struct sockaddr_in *)addr;
return sa->sin_addr.s_addr != htonl(INADDR_ANY);
Expand Down Expand Up @@ -969,7 +969,7 @@ static int nfs23_parse_monolithic(struct fs_context *fc,
{
struct nfs_fs_context *ctx = nfs_fc2context(fc);
struct nfs_fh *mntfh = ctx->mntfh;
struct sockaddr *sap = (struct sockaddr *)&ctx->nfs_server.address;
struct sockaddr_storage *sap = &ctx->nfs_server._address;
int extra_flags = NFS_MOUNT_LEGACY_INTERFACE;
int ret;

Expand Down Expand Up @@ -1044,7 +1044,7 @@ static int nfs23_parse_monolithic(struct fs_context *fc,
memcpy(sap, &data->addr, sizeof(data->addr));
ctx->nfs_server.addrlen = sizeof(data->addr);
ctx->nfs_server.port = ntohs(data->addr.sin_port);
if (sap->sa_family != AF_INET ||
if (sap->ss_family != AF_INET ||
!nfs_verify_server_address(sap))
goto out_no_address;

Expand Down Expand Up @@ -1200,7 +1200,7 @@ static int nfs4_parse_monolithic(struct fs_context *fc,
struct nfs4_mount_data *data)
{
struct nfs_fs_context *ctx = nfs_fc2context(fc);
struct sockaddr *sap = (struct sockaddr *)&ctx->nfs_server.address;
struct sockaddr_storage *sap = &ctx->nfs_server._address;
int ret;
char *c;

Expand Down Expand Up @@ -1314,7 +1314,7 @@ static int nfs_fs_context_validate(struct fs_context *fc)
{
struct nfs_fs_context *ctx = nfs_fc2context(fc);
struct nfs_subversion *nfs_mod;
struct sockaddr *sap = (struct sockaddr *)&ctx->nfs_server.address;
struct sockaddr_storage *sap = &ctx->nfs_server._address;
int max_namelen = PAGE_SIZE;
int max_pathlen = NFS_MAXPATHLEN;
int port = 0;
Expand Down Expand Up @@ -1540,7 +1540,7 @@ static int nfs_init_fs_context(struct fs_context *fc)
ctx->version = nfss->nfs_client->rpc_ops->version;
ctx->minorversion = nfss->nfs_client->cl_minorversion;

memcpy(&ctx->nfs_server.address, &nfss->nfs_client->cl_addr,
memcpy(&ctx->nfs_server._address, &nfss->nfs_client->cl_addr,
ctx->nfs_server.addrlen);

if (fc->net_ns != net) {
Expand Down
14 changes: 7 additions & 7 deletions fs/nfs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ static inline fmode_t flags_to_mode(int flags)
struct nfs_client_initdata {
unsigned long init_flags;
const char *hostname; /* Hostname of the server */
const struct sockaddr *addr; /* Address of the server */
const struct sockaddr_storage *addr; /* Address of the server */
const char *nodename; /* Hostname of the client */
const char *ip_addr; /* IP address of the client */
size_t addrlen;
Expand Down Expand Up @@ -180,7 +180,7 @@ static inline struct nfs_fs_context *nfs_fc2context(const struct fs_context *fc)

/* mount_clnt.c */
struct nfs_mount_request {
struct sockaddr *sap;
struct sockaddr_storage *sap;
size_t salen;
char *hostname;
char *dirpath;
Expand Down Expand Up @@ -223,7 +223,7 @@ extern void nfs4_server_set_init_caps(struct nfs_server *);
extern struct nfs_server *nfs4_create_server(struct fs_context *);
extern struct nfs_server *nfs4_create_referral_server(struct fs_context *);
extern int nfs4_update_server(struct nfs_server *server, const char *hostname,
struct sockaddr *sap, size_t salen,
struct sockaddr_storage *sap, size_t salen,
struct net *net);
extern void nfs_free_server(struct nfs_server *server);
extern struct nfs_server *nfs_clone_server(struct nfs_server *,
Expand All @@ -235,15 +235,15 @@ extern int nfs_client_init_status(const struct nfs_client *clp);
extern int nfs_wait_client_init_complete(const struct nfs_client *clp);
extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
extern struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
const struct sockaddr *ds_addr,
const struct sockaddr_storage *ds_addr,
int ds_addrlen, int ds_proto,
unsigned int ds_timeo,
unsigned int ds_retrans,
u32 minor_version);
extern struct rpc_clnt *nfs4_find_or_create_ds_client(struct nfs_client *,
struct inode *);
extern struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
const struct sockaddr *ds_addr, int ds_addrlen,
const struct sockaddr_storage *ds_addr, int ds_addrlen,
int ds_proto, unsigned int ds_timeo,
unsigned int ds_retrans);
#ifdef CONFIG_PROC_FS
Expand Down Expand Up @@ -894,13 +894,13 @@ static inline bool nfs_error_is_fatal_on_server(int err)
* Select between a default port value and a user-specified port value.
* If a zero value is set, then autobind will be used.
*/
static inline void nfs_set_port(struct sockaddr *sap, int *port,
static inline void nfs_set_port(struct sockaddr_storage *sap, int *port,
const unsigned short default_port)
{
if (*port == NFS_UNSPEC_PORT)
*port = default_port;

rpc_set_port(sap, *port);
rpc_set_port((struct sockaddr *)sap, *port);
}

struct nfs_direct_req {
Expand Down
4 changes: 2 additions & 2 deletions fs/nfs/mount_clnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ int nfs_mount(struct nfs_mount_request *info, int timeo, int retrans)
struct rpc_create_args args = {
.net = info->net,
.protocol = info->protocol,
.address = info->sap,
.address = (struct sockaddr *)info->sap,
.addrsize = info->salen,
.timeout = &mnt_timeout,
.servername = info->hostname,
Expand Down Expand Up @@ -245,7 +245,7 @@ void nfs_umount(const struct nfs_mount_request *info)
struct rpc_create_args args = {
.net = info->net,
.protocol = IPPROTO_UDP,
.address = info->sap,
.address = (struct sockaddr *)info->sap,
.addrsize = info->salen,
.timeout = &nfs_umnt_timeout,
.servername = info->hostname,
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ struct vfsmount *nfs_d_automount(struct path *path)
}

/* for submounts we want the same server; referrals will reassign */
memcpy(&ctx->nfs_server.address, &client->cl_addr, client->cl_addrlen);
memcpy(&ctx->nfs_server._address, &client->cl_addr, client->cl_addrlen);
ctx->nfs_server.addrlen = client->cl_addrlen;
ctx->nfs_server.port = server->port;

Expand Down
4 changes: 2 additions & 2 deletions fs/nfs/nfs3client.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ struct nfs_server *nfs3_clone_server(struct nfs_server *source,
* the MDS.
*/
struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
const struct sockaddr *ds_addr, int ds_addrlen,
const struct sockaddr_storage *ds_addr, int ds_addrlen,
int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans)
{
struct rpc_timeout ds_timeout;
Expand All @@ -98,7 +98,7 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
char buf[INET6_ADDRSTRLEN + 1];

/* fake a hostname because lockd wants it */
if (rpc_ntop(ds_addr, buf, sizeof(buf)) <= 0)
if (rpc_ntop((struct sockaddr *)ds_addr, buf, sizeof(buf)) <= 0)
return ERR_PTR(-EINVAL);
cl_init.hostname = buf;

Expand Down
3 changes: 3 additions & 0 deletions fs/nfs/nfs42proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,9 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
&args.seq_args, &res.seq_res, 0);
trace_nfs4_clone(src_inode, dst_inode, &args, status);
if (status == 0) {
/* a zero-length count means clone to EOF in src */
if (count == 0 && res.dst_fattr->valid & NFS_ATTR_FATTR_SIZE)
count = nfs_size_to_loff_t(res.dst_fattr->size) - dst_offset;
nfs42_copy_dest_done(dst_inode, dst_offset, count);
status = nfs_post_op_update_inode(dst_inode, res.dst_fattr);
}
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/nfs4_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ struct rpc_clnt *nfs4_negotiate_security(struct rpc_clnt *, struct inode *,
int nfs4_submount(struct fs_context *, struct nfs_server *);
int nfs4_replace_transport(struct nfs_server *server,
const struct nfs4_fs_locations *locations);
size_t nfs_parse_server_name(char *string, size_t len, struct sockaddr *sa,
size_t nfs_parse_server_name(char *string, size_t len, struct sockaddr_storage *ss,
size_t salen, struct net *net, int port);
/* nfs4proc.c */
extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *);
Expand Down
19 changes: 10 additions & 9 deletions fs/nfs/nfs4client.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ int nfs40_init_client(struct nfs_client *clp)
ret = nfs4_setup_slot_table(tbl, NFS4_MAX_SLOT_TABLE,
"NFSv4.0 transport Slot table");
if (ret) {
nfs4_shutdown_slot_table(tbl);
kfree(tbl);
return ret;
}
Expand Down Expand Up @@ -889,7 +890,7 @@ nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
*/
static int nfs4_set_client(struct nfs_server *server,
const char *hostname,
const struct sockaddr *addr,
const struct sockaddr_storage *addr,
const size_t addrlen,
const char *ip_addr,
int proto, const struct rpc_timeout *timeparms,
Expand Down Expand Up @@ -924,7 +925,7 @@ static int nfs4_set_client(struct nfs_server *server,
__set_bit(NFS_CS_MIGRATION, &cl_init.init_flags);
if (test_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status))
__set_bit(NFS_CS_TSM_POSSIBLE, &cl_init.init_flags);
server->port = rpc_get_port(addr);
server->port = rpc_get_port((struct sockaddr *)addr);

/* Allocate or find a client reference we can use */
clp = nfs_get_client(&cl_init);
Expand Down Expand Up @@ -960,7 +961,7 @@ static int nfs4_set_client(struct nfs_server *server,
* the MDS.
*/
struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
const struct sockaddr *ds_addr, int ds_addrlen,
const struct sockaddr_storage *ds_addr, int ds_addrlen,
int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans,
u32 minor_version)
{
Expand All @@ -980,7 +981,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
};
char buf[INET6_ADDRSTRLEN + 1];

if (rpc_ntop(ds_addr, buf, sizeof(buf)) <= 0)
if (rpc_ntop((struct sockaddr *)ds_addr, buf, sizeof(buf)) <= 0)
return ERR_PTR(-EINVAL);
cl_init.hostname = buf;

Expand Down Expand Up @@ -1148,7 +1149,7 @@ static int nfs4_init_server(struct nfs_server *server, struct fs_context *fc)
/* Get a client record */
error = nfs4_set_client(server,
ctx->nfs_server.hostname,
&ctx->nfs_server.address,
&ctx->nfs_server._address,
ctx->nfs_server.addrlen,
ctx->client_address,
ctx->nfs_server.protocol,
Expand Down Expand Up @@ -1238,7 +1239,7 @@ struct nfs_server *nfs4_create_referral_server(struct fs_context *fc)
rpc_set_port(&ctx->nfs_server.address, NFS_RDMA_PORT);
error = nfs4_set_client(server,
ctx->nfs_server.hostname,
&ctx->nfs_server.address,
&ctx->nfs_server._address,
ctx->nfs_server.addrlen,
parent_client->cl_ipaddr,
XPRT_TRANSPORT_RDMA,
Expand All @@ -1254,7 +1255,7 @@ struct nfs_server *nfs4_create_referral_server(struct fs_context *fc)
rpc_set_port(&ctx->nfs_server.address, NFS_PORT);
error = nfs4_set_client(server,
ctx->nfs_server.hostname,
&ctx->nfs_server.address,
&ctx->nfs_server._address,
ctx->nfs_server.addrlen,
parent_client->cl_ipaddr,
XPRT_TRANSPORT_TCP,
Expand Down Expand Up @@ -1303,14 +1304,14 @@ struct nfs_server *nfs4_create_referral_server(struct fs_context *fc)
* Returns zero on success, or a negative errno value.
*/
int nfs4_update_server(struct nfs_server *server, const char *hostname,
struct sockaddr *sap, size_t salen, struct net *net)
struct sockaddr_storage *sap, size_t salen, struct net *net)
{
struct nfs_client *clp = server->nfs_client;
struct rpc_clnt *clnt = server->client;
struct xprt_create xargs = {
.ident = clp->cl_proto,
.net = net,
.dstaddr = sap,
.dstaddr = (struct sockaddr *)sap,
.addrlen = salen,
.servername = hostname,
};
Expand Down
Loading

0 comments on commit 31fc92f

Please sign in to comment.