aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-07-26 04:15:54 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2011-07-26 15:07:43 -0400
commite57712ebebbb9db7d8dcef216437b3171ddcf115 (patch)
tree484b748a272fe32385ca37d4d87ace7d4e8732bb
parent03209378b4b25775bf5e6a86e86f074a1057a439 (diff)
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>
-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