diff options
Diffstat (limited to 'fs/inotify_user.c')
| -rw-r--r-- | fs/inotify_user.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/fs/inotify_user.c b/fs/inotify_user.c index 6676c06bb7c1..60249429a253 100644 --- a/fs/inotify_user.c +++ b/fs/inotify_user.c | |||
| @@ -354,20 +354,20 @@ static void inotify_dev_event_dequeue(struct inotify_device *dev) | |||
| 354 | } | 354 | } |
| 355 | 355 | ||
| 356 | /* | 356 | /* |
| 357 | * find_inode - resolve a user-given path to a specific inode and return a nd | 357 | * find_inode - resolve a user-given path to a specific inode |
| 358 | */ | 358 | */ |
| 359 | static int find_inode(const char __user *dirname, struct nameidata *nd, | 359 | static int find_inode(const char __user *dirname, struct path *path, |
| 360 | unsigned flags) | 360 | unsigned flags) |
| 361 | { | 361 | { |
| 362 | int error; | 362 | int error; |
| 363 | 363 | ||
| 364 | error = __user_walk(dirname, flags, nd); | 364 | error = user_path_at(AT_FDCWD, dirname, flags, path); |
| 365 | if (error) | 365 | if (error) |
| 366 | return error; | 366 | return error; |
| 367 | /* you can only watch an inode if you have read permissions on it */ | 367 | /* you can only watch an inode if you have read permissions on it */ |
| 368 | error = vfs_permission(nd, MAY_READ); | 368 | error = inode_permission(path->dentry->d_inode, MAY_READ); |
| 369 | if (error) | 369 | if (error) |
| 370 | path_put(&nd->path); | 370 | path_put(path); |
| 371 | return error; | 371 | return error; |
| 372 | } | 372 | } |
| 373 | 373 | ||
| @@ -566,7 +566,7 @@ static const struct inotify_operations inotify_user_ops = { | |||
| 566 | .destroy_watch = free_inotify_user_watch, | 566 | .destroy_watch = free_inotify_user_watch, |
| 567 | }; | 567 | }; |
| 568 | 568 | ||
| 569 | asmlinkage long sys_inotify_init(void) | 569 | asmlinkage long sys_inotify_init1(int flags) |
| 570 | { | 570 | { |
| 571 | struct inotify_device *dev; | 571 | struct inotify_device *dev; |
| 572 | struct inotify_handle *ih; | 572 | struct inotify_handle *ih; |
| @@ -574,7 +574,14 @@ asmlinkage long sys_inotify_init(void) | |||
| 574 | struct file *filp; | 574 | struct file *filp; |
| 575 | int fd, ret; | 575 | int fd, ret; |
| 576 | 576 | ||
| 577 | fd = get_unused_fd(); | 577 | /* Check the IN_* constants for consistency. */ |
| 578 | BUILD_BUG_ON(IN_CLOEXEC != O_CLOEXEC); | ||
| 579 | BUILD_BUG_ON(IN_NONBLOCK != O_NONBLOCK); | ||
| 580 | |||
| 581 | if (flags & ~(IN_CLOEXEC | IN_NONBLOCK)) | ||
| 582 | return -EINVAL; | ||
| 583 | |||
| 584 | fd = get_unused_fd_flags(flags & O_CLOEXEC); | ||
| 578 | if (fd < 0) | 585 | if (fd < 0) |
| 579 | return fd; | 586 | return fd; |
| 580 | 587 | ||
| @@ -610,7 +617,7 @@ asmlinkage long sys_inotify_init(void) | |||
| 610 | filp->f_path.dentry = dget(inotify_mnt->mnt_root); | 617 | filp->f_path.dentry = dget(inotify_mnt->mnt_root); |
| 611 | filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping; | 618 | filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping; |
| 612 | filp->f_mode = FMODE_READ; | 619 | filp->f_mode = FMODE_READ; |
| 613 | filp->f_flags = O_RDONLY; | 620 | filp->f_flags = O_RDONLY | (flags & O_NONBLOCK); |
| 614 | filp->private_data = dev; | 621 | filp->private_data = dev; |
| 615 | 622 | ||
| 616 | INIT_LIST_HEAD(&dev->events); | 623 | INIT_LIST_HEAD(&dev->events); |
| @@ -638,11 +645,16 @@ out_put_fd: | |||
| 638 | return ret; | 645 | return ret; |
| 639 | } | 646 | } |
| 640 | 647 | ||
| 641 | asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) | 648 | asmlinkage long sys_inotify_init(void) |
| 649 | { | ||
| 650 | return sys_inotify_init1(0); | ||
| 651 | } | ||
| 652 | |||
| 653 | asmlinkage long sys_inotify_add_watch(int fd, const char __user *pathname, u32 mask) | ||
| 642 | { | 654 | { |
| 643 | struct inode *inode; | 655 | struct inode *inode; |
| 644 | struct inotify_device *dev; | 656 | struct inotify_device *dev; |
| 645 | struct nameidata nd; | 657 | struct path path; |
| 646 | struct file *filp; | 658 | struct file *filp; |
| 647 | int ret, fput_needed; | 659 | int ret, fput_needed; |
| 648 | unsigned flags = 0; | 660 | unsigned flags = 0; |
| @@ -662,12 +674,12 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) | |||
| 662 | if (mask & IN_ONLYDIR) | 674 | if (mask & IN_ONLYDIR) |
| 663 | flags |= LOOKUP_DIRECTORY; | 675 | flags |= LOOKUP_DIRECTORY; |
| 664 | 676 | ||
| 665 | ret = find_inode(path, &nd, flags); | 677 | ret = find_inode(pathname, &path, flags); |
| 666 | if (unlikely(ret)) | 678 | if (unlikely(ret)) |
| 667 | goto fput_and_out; | 679 | goto fput_and_out; |
| 668 | 680 | ||
| 669 | /* inode held in place by reference to nd; dev by fget on fd */ | 681 | /* inode held in place by reference to path; dev by fget on fd */ |
| 670 | inode = nd.path.dentry->d_inode; | 682 | inode = path.dentry->d_inode; |
| 671 | dev = filp->private_data; | 683 | dev = filp->private_data; |
| 672 | 684 | ||
| 673 | mutex_lock(&dev->up_mutex); | 685 | mutex_lock(&dev->up_mutex); |
| @@ -676,7 +688,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) | |||
| 676 | ret = create_watch(dev, inode, mask); | 688 | ret = create_watch(dev, inode, mask); |
| 677 | mutex_unlock(&dev->up_mutex); | 689 | mutex_unlock(&dev->up_mutex); |
| 678 | 690 | ||
| 679 | path_put(&nd.path); | 691 | path_put(&path); |
| 680 | fput_and_out: | 692 | fput_and_out: |
| 681 | fput_light(filp, fput_needed); | 693 | fput_light(filp, fput_needed); |
| 682 | return ret; | 694 | return ret; |
