mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
merge fchmod() and fchmodat() guts, kill ancient broken kludge
The kludge in question is undocumented and doesn't work for 32bit binaries on amd64, sparc64 and s390. Passing (mode_t)-1 as mode had (since 0.99.14v and contrary to behaviour of any other Unix, prescriptions of POSIX, SuS and our own manpages) was kinda-sorta no-op. Note that any software relying on that (and looking for examples shows none) would be visibly broken on sparc64, where practically all userland is built 32bit. No such complaints noticed... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
03209378b4
commit
e57712ebeb
1 changed files with 28 additions and 50 deletions
78
fs/open.c
78
fs/open.c
|
@ -446,74 +446,52 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)
|
|||
return error;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
|
||||
static int chmod_common(struct path *path, umode_t mode)
|
||||
{
|
||||
struct inode * inode;
|
||||
struct dentry * dentry;
|
||||
struct file * file;
|
||||
int err = -EBADF;
|
||||
struct inode *inode = path->dentry->d_inode;
|
||||
struct iattr newattrs;
|
||||
int error;
|
||||
|
||||
file = fget(fd);
|
||||
if (!file)
|
||||
goto out;
|
||||
|
||||
dentry = file->f_path.dentry;
|
||||
inode = dentry->d_inode;
|
||||
|
||||
audit_inode(NULL, dentry);
|
||||
|
||||
err = mnt_want_write_file(file);
|
||||
if (err)
|
||||
goto out_putf;
|
||||
error = mnt_want_write(path->mnt);
|
||||
if (error)
|
||||
return error;
|
||||
mutex_lock(&inode->i_mutex);
|
||||
err = security_path_chmod(dentry, file->f_vfsmnt, mode);
|
||||
if (err)
|
||||
error = security_path_chmod(path->dentry, path->mnt, mode);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
if (mode == (mode_t) -1)
|
||||
mode = inode->i_mode;
|
||||
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
|
||||
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
|
||||
err = notify_change(dentry, &newattrs);
|
||||
error = notify_change(path->dentry, &newattrs);
|
||||
out_unlock:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
mnt_drop_write(file->f_path.mnt);
|
||||
out_putf:
|
||||
fput(file);
|
||||
out:
|
||||
mnt_drop_write(path->mnt);
|
||||
return error;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
|
||||
{
|
||||
struct file * file;
|
||||
int err = -EBADF;
|
||||
|
||||
file = fget(fd);
|
||||
if (file) {
|
||||
audit_inode(NULL, file->f_path.dentry);
|
||||
err = chmod_common(&file->f_path, mode);
|
||||
fput(file);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode)
|
||||
{
|
||||
struct path path;
|
||||
struct inode *inode;
|
||||
int error;
|
||||
struct iattr newattrs;
|
||||
|
||||
error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
|
||||
if (error)
|
||||
goto out;
|
||||
inode = path.dentry->d_inode;
|
||||
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (error)
|
||||
goto dput_and_out;
|
||||
mutex_lock(&inode->i_mutex);
|
||||
error = security_path_chmod(path.dentry, path.mnt, mode);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
if (mode == (mode_t) -1)
|
||||
mode = inode->i_mode;
|
||||
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
|
||||
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
|
||||
error = notify_change(path.dentry, &newattrs);
|
||||
out_unlock:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
mnt_drop_write(path.mnt);
|
||||
dput_and_out:
|
||||
path_put(&path);
|
||||
out:
|
||||
if (!error) {
|
||||
error = chmod_common(&path, mode);
|
||||
path_put(&path);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue