summaryrefslogtreecommitdiffstats
path: root/fs/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/open.c')
-rw-r--r--fs/open.c78
1 files changed, 28 insertions, 50 deletions
diff --git a/fs/open.c b/fs/open.c
index 739b751aa73e..f71192109457 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -446,74 +446,52 @@ out:
446 return error; 446 return error;
447} 447}
448 448
449SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode) 449static int chmod_common(struct path *path, umode_t mode)
450{ 450{
451 struct inode * inode; 451 struct inode *inode = path->dentry->d_inode;
452 struct dentry * dentry;
453 struct file * file;
454 int err = -EBADF;
455 struct iattr newattrs; 452 struct iattr newattrs;
453 int error;
456 454
457 file = fget(fd); 455 error = mnt_want_write(path->mnt);
458 if (!file) 456 if (error)
459 goto out; 457 return error;
460
461 dentry = file->f_path.dentry;
462 inode = dentry->d_inode;
463
464 audit_inode(NULL, dentry);
465
466 err = mnt_want_write_file(file);
467 if (err)
468 goto out_putf;
469 mutex_lock(&inode->i_mutex); 458 mutex_lock(&inode->i_mutex);
470 err = security_path_chmod(dentry, file->f_vfsmnt, mode); 459 error = security_path_chmod(path->dentry, path->mnt, mode);
471 if (err) 460 if (error)
472 goto out_unlock; 461 goto out_unlock;
473 if (mode == (mode_t) -1)
474 mode = inode->i_mode;
475 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); 462 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
476 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; 463 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
477 err = notify_change(dentry, &newattrs); 464 error = notify_change(path->dentry, &newattrs);
478out_unlock: 465out_unlock:
479 mutex_unlock(&inode->i_mutex); 466 mutex_unlock(&inode->i_mutex);
480 mnt_drop_write(file->f_path.mnt); 467 mnt_drop_write(path->mnt);
481out_putf: 468 return error;
482 fput(file); 469}
483out: 470
471SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
472{
473 struct file * file;
474 int err = -EBADF;
475
476 file = fget(fd);
477 if (file) {
478 audit_inode(NULL, file->f_path.dentry);
479 err = chmod_common(&file->f_path, mode);
480 fput(file);
481 }
484 return err; 482 return err;
485} 483}
486 484
487SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode) 485SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode)
488{ 486{
489 struct path path; 487 struct path path;
490 struct inode *inode;
491 int error; 488 int error;
492 struct iattr newattrs;
493 489
494 error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); 490 error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
495 if (error) 491 if (!error) {
496 goto out; 492 error = chmod_common(&path, mode);
497 inode = path.dentry->d_inode; 493 path_put(&path);
498 494 }
499 error = mnt_want_write(path.mnt);
500 if (error)
501 goto dput_and_out;
502 mutex_lock(&inode->i_mutex);
503 error = security_path_chmod(path.dentry, path.mnt, mode);
504 if (error)
505 goto out_unlock;
506 if (mode == (mode_t) -1)
507 mode = inode->i_mode;
508 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
509 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
510 error = notify_change(path.dentry, &newattrs);
511out_unlock:
512 mutex_unlock(&inode->i_mutex);
513 mnt_drop_write(path.mnt);
514dput_and_out:
515 path_put(&path);
516out:
517 return error; 495 return error;
518} 496}
519 497