diff options
| -rw-r--r-- | fs/fuse/inode.c | 78 |
1 files changed, 72 insertions, 6 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 9aa6f46d0c32..e54ddbda208c 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/seq_file.h> | 14 | #include <linux/seq_file.h> |
| 15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/moduleparam.h> | ||
| 17 | #include <linux/parser.h> | 18 | #include <linux/parser.h> |
| 18 | #include <linux/statfs.h> | 19 | #include <linux/statfs.h> |
| 19 | #include <linux/random.h> | 20 | #include <linux/random.h> |
| @@ -28,6 +29,24 @@ static struct kmem_cache *fuse_inode_cachep; | |||
| 28 | struct list_head fuse_conn_list; | 29 | struct list_head fuse_conn_list; |
| 29 | DEFINE_MUTEX(fuse_mutex); | 30 | DEFINE_MUTEX(fuse_mutex); |
| 30 | 31 | ||
| 32 | static int set_global_limit(const char *val, struct kernel_param *kp); | ||
| 33 | |||
| 34 | static unsigned max_user_bgreq; | ||
| 35 | module_param_call(max_user_bgreq, set_global_limit, param_get_uint, | ||
| 36 | &max_user_bgreq, 0644); | ||
| 37 | __MODULE_PARM_TYPE(max_user_bgreq, "uint"); | ||
| 38 | MODULE_PARM_DESC(max_user_bgreq, | ||
| 39 | "Global limit for the maximum number of backgrounded requests an " | ||
| 40 | "unprivileged user can set"); | ||
| 41 | |||
| 42 | static unsigned max_user_congthresh; | ||
| 43 | module_param_call(max_user_congthresh, set_global_limit, param_get_uint, | ||
| 44 | &max_user_congthresh, 0644); | ||
| 45 | __MODULE_PARM_TYPE(max_user_congthresh, "uint"); | ||
| 46 | MODULE_PARM_DESC(max_user_congthresh, | ||
| 47 | "Global limit for the maximum congestion threshold an " | ||
| 48 | "unprivileged user can set"); | ||
| 49 | |||
| 31 | #define FUSE_SUPER_MAGIC 0x65735546 | 50 | #define FUSE_SUPER_MAGIC 0x65735546 |
| 32 | 51 | ||
| 33 | #define FUSE_DEFAULT_BLKSIZE 512 | 52 | #define FUSE_DEFAULT_BLKSIZE 512 |
| @@ -735,6 +754,54 @@ static const struct super_operations fuse_super_operations = { | |||
| 735 | .show_options = fuse_show_options, | 754 | .show_options = fuse_show_options, |
| 736 | }; | 755 | }; |
| 737 | 756 | ||
| 757 | static void sanitize_global_limit(unsigned *limit) | ||
| 758 | { | ||
| 759 | if (*limit == 0) | ||
| 760 | *limit = ((num_physpages << PAGE_SHIFT) >> 13) / | ||
| 761 | sizeof(struct fuse_req); | ||
| 762 | |||
| 763 | if (*limit >= 1 << 16) | ||
| 764 | *limit = (1 << 16) - 1; | ||
| 765 | } | ||
| 766 | |||
| 767 | static int set_global_limit(const char *val, struct kernel_param *kp) | ||
| 768 | { | ||
| 769 | int rv; | ||
| 770 | |||
| 771 | rv = param_set_uint(val, kp); | ||
| 772 | if (rv) | ||
| 773 | return rv; | ||
| 774 | |||
| 775 | sanitize_global_limit((unsigned *)kp->arg); | ||
| 776 | |||
| 777 | return 0; | ||
| 778 | } | ||
| 779 | |||
| 780 | static void process_init_limits(struct fuse_conn *fc, struct fuse_init_out *arg) | ||
| 781 | { | ||
| 782 | int cap_sys_admin = capable(CAP_SYS_ADMIN); | ||
| 783 | |||
| 784 | if (arg->minor < 13) | ||
| 785 | return; | ||
| 786 | |||
| 787 | sanitize_global_limit(&max_user_bgreq); | ||
| 788 | sanitize_global_limit(&max_user_congthresh); | ||
| 789 | |||
| 790 | if (arg->max_background) { | ||
| 791 | fc->max_background = arg->max_background; | ||
| 792 | |||
| 793 | if (!cap_sys_admin && fc->max_background > max_user_bgreq) | ||
| 794 | fc->max_background = max_user_bgreq; | ||
| 795 | } | ||
| 796 | if (arg->congestion_threshold) { | ||
| 797 | fc->congestion_threshold = arg->congestion_threshold; | ||
| 798 | |||
| 799 | if (!cap_sys_admin && | ||
| 800 | fc->congestion_threshold > max_user_congthresh) | ||
| 801 | fc->congestion_threshold = max_user_congthresh; | ||
| 802 | } | ||
| 803 | } | ||
| 804 | |||
| 738 | static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | 805 | static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) |
| 739 | { | 806 | { |
| 740 | struct fuse_init_out *arg = &req->misc.init_out; | 807 | struct fuse_init_out *arg = &req->misc.init_out; |
| @@ -744,12 +811,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
| 744 | else { | 811 | else { |
| 745 | unsigned long ra_pages; | 812 | unsigned long ra_pages; |
| 746 | 813 | ||
| 747 | if (arg->minor >= 13) { | 814 | process_init_limits(fc, arg); |
| 748 | if (arg->max_background) | 815 | |
| 749 | fc->max_background = arg->max_background; | ||
| 750 | if (arg->congestion_threshold) | ||
| 751 | fc->congestion_threshold = arg->congestion_threshold; | ||
| 752 | } | ||
| 753 | if (arg->minor >= 6) { | 816 | if (arg->minor >= 6) { |
| 754 | ra_pages = arg->max_readahead / PAGE_CACHE_SIZE; | 817 | ra_pages = arg->max_readahead / PAGE_CACHE_SIZE; |
| 755 | if (arg->flags & FUSE_ASYNC_READ) | 818 | if (arg->flags & FUSE_ASYNC_READ) |
| @@ -1161,6 +1224,9 @@ static int __init fuse_init(void) | |||
| 1161 | if (res) | 1224 | if (res) |
| 1162 | goto err_sysfs_cleanup; | 1225 | goto err_sysfs_cleanup; |
| 1163 | 1226 | ||
| 1227 | sanitize_global_limit(&max_user_bgreq); | ||
| 1228 | sanitize_global_limit(&max_user_congthresh); | ||
| 1229 | |||
| 1164 | return 0; | 1230 | return 0; |
| 1165 | 1231 | ||
| 1166 | err_sysfs_cleanup: | 1232 | err_sysfs_cleanup: |
