|
@@ -446,74 +446,52 @@ out:
|
|
|
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;
|
|
|
}
|
|
|
|