Updated from Linux LTS 3.10.20 to 3.10.21

This commit is contained in:
Nathan
2025-04-07 09:52:38 -05:00
parent d67348cc45
commit 8de512f759
67 changed files with 803 additions and 353 deletions

View File

@@ -56,10 +56,19 @@ static void configfs_d_iput(struct dentry * dentry,
struct configfs_dirent *sd = dentry->d_fsdata;
if (sd) {
BUG_ON(sd->s_dentry != dentry);
/* Coordinate with configfs_readdir */
spin_lock(&configfs_dirent_lock);
sd->s_dentry = NULL;
/* Coordinate with configfs_attach_attr where will increase
* sd->s_count and update sd->s_dentry to new allocated one.
* Only set sd->dentry to null when this dentry is the only
* sd owner.
* If not do so, configfs_d_iput may run just after
* configfs_attach_attr and set sd->s_dentry to null
* even it's still in use.
*/
if (atomic_read(&sd->s_count) <= 2)
sd->s_dentry = NULL;
spin_unlock(&configfs_dirent_lock);
configfs_put(sd);
}
@@ -426,8 +435,11 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den
struct configfs_attribute * attr = sd->s_element;
int error;
spin_lock(&configfs_dirent_lock);
dentry->d_fsdata = configfs_get(sd);
sd->s_dentry = dentry;
spin_unlock(&configfs_dirent_lock);
error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG,
configfs_init_file);
if (error) {

View File

@@ -1671,6 +1671,12 @@ int __get_dumpable(unsigned long mm_flags)
return (ret > SUID_DUMP_USER) ? SUID_DUMP_ROOT : ret;
}
/*
* This returns the actual value of the suid_dumpable flag. For things
* that are using this for checking for privilege transitions, it must
* test against SUID_DUMP_USER rather than treating it as a boolean
* value.
*/
int get_dumpable(struct mm_struct *mm)
{
return __get_dumpable(mm->flags);

View File

@@ -1160,29 +1160,24 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data)
int ret;
if (!data->rpc_done) {
ret = data->rpc_status;
goto err;
if (data->rpc_status) {
ret = data->rpc_status;
goto err;
}
/* cached opens have already been processed */
goto update;
}
ret = -ESTALE;
if (!(data->f_attr.valid & NFS_ATTR_FATTR_TYPE) ||
!(data->f_attr.valid & NFS_ATTR_FATTR_FILEID) ||
!(data->f_attr.valid & NFS_ATTR_FATTR_CHANGE))
goto err;
ret = -ENOMEM;
state = nfs4_get_open_state(inode, data->owner);
if (state == NULL)
goto err;
ret = nfs_refresh_inode(inode, &data->f_attr);
if (ret)
goto err;
if (data->o_res.delegation_type != 0)
nfs4_opendata_check_deleg(data, state);
update:
update_open_stateid(state, &data->o_res.stateid, NULL,
data->o_arg.fmode);
atomic_inc(&state->count);
return state;
err:
@@ -4572,6 +4567,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
status = 0;
}
request->fl_ops->fl_release_private(request);
request->fl_ops = NULL;
out:
return status;
}

View File

@@ -536,16 +536,12 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
if (err)
goto out3;
exp.ex_anon_uid= make_kuid(&init_user_ns, an_int);
if (!uid_valid(exp.ex_anon_uid))
goto out3;
/* anon gid */
err = get_int(&mesg, &an_int);
if (err)
goto out3;
exp.ex_anon_gid= make_kgid(&init_user_ns, an_int);
if (!gid_valid(exp.ex_anon_gid))
goto out3;
/* fsid */
err = get_int(&mesg, &an_int);
@@ -583,6 +579,17 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
exp.ex_uuid);
if (err)
goto out4;
/*
* For some reason exportfs has been passing down an
* invalid (-1) uid & gid on the "dummy" export which it
* uses to test export support. To make sure exportfs
* sees errors from check_export we therefore need to
* delay these checks till after check_export:
*/
if (!uid_valid(exp.ex_anon_uid))
goto out4;
if (!gid_valid(exp.ex_anon_gid))
goto out4;
}
expp = svc_export_lookup(&exp);

View File

@@ -297,8 +297,104 @@ commit_metadata(struct svc_fh *fhp)
}
/*
* Set various file attributes.
* N.B. After this call fhp needs an fh_put
* Go over the attributes and take care of the small differences between
* NFS semantics and what Linux expects.
*/
static void
nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap)
{
/*
* NFSv2 does not differentiate between "set-[ac]time-to-now"
* which only requires access, and "set-[ac]time-to-X" which
* requires ownership.
* So if it looks like it might be "set both to the same time which
* is close to now", and if inode_change_ok fails, then we
* convert to "set to now" instead of "set to explicit time"
*
* We only call inode_change_ok as the last test as technically
* it is not an interface that we should be using.
*/
#define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET)
#define MAX_TOUCH_TIME_ERROR (30*60)
if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET &&
iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec) {
/*
* Looks probable.
*
* Now just make sure time is in the right ballpark.
* Solaris, at least, doesn't seem to care what the time
* request is. We require it be within 30 minutes of now.
*/
time_t delta = iap->ia_atime.tv_sec - get_seconds();
if (delta < 0)
delta = -delta;
if (delta < MAX_TOUCH_TIME_ERROR &&
inode_change_ok(inode, iap) != 0) {
/*
* Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME.
* This will cause notify_change to set these times
* to "now"
*/
iap->ia_valid &= ~BOTH_TIME_SET;
}
}
/* sanitize the mode change */
if (iap->ia_valid & ATTR_MODE) {
iap->ia_mode &= S_IALLUGO;
iap->ia_mode |= (inode->i_mode & ~S_IALLUGO);
}
/* Revoke setuid/setgid on chown */
if (!S_ISDIR(inode->i_mode) &&
(((iap->ia_valid & ATTR_UID) && !uid_eq(iap->ia_uid, inode->i_uid)) ||
((iap->ia_valid & ATTR_GID) && !gid_eq(iap->ia_gid, inode->i_gid)))) {
iap->ia_valid |= ATTR_KILL_PRIV;
if (iap->ia_valid & ATTR_MODE) {
/* we're setting mode too, just clear the s*id bits */
iap->ia_mode &= ~S_ISUID;
if (iap->ia_mode & S_IXGRP)
iap->ia_mode &= ~S_ISGID;
} else {
/* set ATTR_KILL_* bits and let VFS handle it */
iap->ia_valid |= (ATTR_KILL_SUID | ATTR_KILL_SGID);
}
}
}
static __be32
nfsd_get_write_access(struct svc_rqst *rqstp, struct svc_fh *fhp,
struct iattr *iap)
{
struct inode *inode = fhp->fh_dentry->d_inode;
int host_err;
if (iap->ia_size < inode->i_size) {
__be32 err;
err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
NFSD_MAY_TRUNC | NFSD_MAY_OWNER_OVERRIDE);
if (err)
return err;
}
host_err = get_write_access(inode);
if (host_err)
goto out_nfserrno;
host_err = locks_verify_truncate(inode, NULL, iap->ia_size);
if (host_err)
goto out_put_write_access;
return 0;
out_put_write_access:
put_write_access(inode);
out_nfserrno:
return nfserrno(host_err);
}
/*
* Set various file attributes. After this call fhp needs an fh_put.
*/
__be32
nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
@@ -332,114 +428,43 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
if (!iap->ia_valid)
goto out;
nfsd_sanitize_attrs(inode, iap);
/*
* NFSv2 does not differentiate between "set-[ac]time-to-now"
* which only requires access, and "set-[ac]time-to-X" which
* requires ownership.
* So if it looks like it might be "set both to the same time which
* is close to now", and if inode_change_ok fails, then we
* convert to "set to now" instead of "set to explicit time"
*
* We only call inode_change_ok as the last test as technically
* it is not an interface that we should be using. It is only
* valid if the filesystem does not define it's own i_op->setattr.
*/
#define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET)
#define MAX_TOUCH_TIME_ERROR (30*60)
if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET &&
iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec) {
/*
* Looks probable.
*
* Now just make sure time is in the right ballpark.
* Solaris, at least, doesn't seem to care what the time
* request is. We require it be within 30 minutes of now.
*/
time_t delta = iap->ia_atime.tv_sec - get_seconds();
if (delta < 0)
delta = -delta;
if (delta < MAX_TOUCH_TIME_ERROR &&
inode_change_ok(inode, iap) != 0) {
/*
* Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME.
* This will cause notify_change to set these times
* to "now"
*/
iap->ia_valid &= ~BOTH_TIME_SET;
}
}
/*
* The size case is special.
* It changes the file as well as the attributes.
* The size case is special, it changes the file in addition to the
* attributes.
*/
if (iap->ia_valid & ATTR_SIZE) {
if (iap->ia_size < inode->i_size) {
err = nfsd_permission(rqstp, fhp->fh_export, dentry,
NFSD_MAY_TRUNC|NFSD_MAY_OWNER_OVERRIDE);
if (err)
goto out;
}
host_err = get_write_access(inode);
if (host_err)
goto out_nfserr;
err = nfsd_get_write_access(rqstp, fhp, iap);
if (err)
goto out;
size_change = 1;
host_err = locks_verify_truncate(inode, NULL, iap->ia_size);
if (host_err) {
put_write_access(inode);
goto out_nfserr;
}
}
/* sanitize the mode change */
if (iap->ia_valid & ATTR_MODE) {
iap->ia_mode &= S_IALLUGO;
iap->ia_mode |= (inode->i_mode & ~S_IALLUGO);
}
/* Revoke setuid/setgid on chown */
if (!S_ISDIR(inode->i_mode) &&
(((iap->ia_valid & ATTR_UID) && !uid_eq(iap->ia_uid, inode->i_uid)) ||
((iap->ia_valid & ATTR_GID) && !gid_eq(iap->ia_gid, inode->i_gid)))) {
iap->ia_valid |= ATTR_KILL_PRIV;
if (iap->ia_valid & ATTR_MODE) {
/* we're setting mode too, just clear the s*id bits */
iap->ia_mode &= ~S_ISUID;
if (iap->ia_mode & S_IXGRP)
iap->ia_mode &= ~S_ISGID;
} else {
/* set ATTR_KILL_* bits and let VFS handle it */
iap->ia_valid |= (ATTR_KILL_SUID | ATTR_KILL_SGID);
}
}
/* Change the attributes. */
iap->ia_valid |= ATTR_CTIME;
err = nfserr_notsync;
if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
host_err = nfsd_break_lease(inode);
if (host_err)
goto out_nfserr;
fh_lock(fhp);
host_err = notify_change(dentry, iap);
err = nfserrno(host_err);
fh_unlock(fhp);
if (check_guard && guardtime != inode->i_ctime.tv_sec) {
err = nfserr_notsync;
goto out_put_write_access;
}
host_err = nfsd_break_lease(inode);
if (host_err)
goto out_put_write_access_nfserror;
fh_lock(fhp);
host_err = notify_change(dentry, iap);
fh_unlock(fhp);
out_put_write_access_nfserror:
err = nfserrno(host_err);
out_put_write_access:
if (size_change)
put_write_access(inode);
if (!err)
commit_metadata(fhp);
out:
return err;
out_nfserr:
err = nfserrno(host_err);
goto out;
}
#if defined(CONFIG_NFSD_V2_ACL) || \