X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=kernel%2Fucount.c;h=9d20d5dd298af25d0cd95635e217180601703959;hb=8bf371e6adff29758cc3c57c17df4486513081f8;hp=33c418718304c6d0cb781d174cf69f592f2d54bb;hpb=f6b2db1a3e8d141dd144df58900fb0444d5d7c53;p=cascardo%2Flinux.git diff --git a/kernel/ucount.c b/kernel/ucount.c index 33c418718304..9d20d5dd298a 100644 --- a/kernel/ucount.c +++ b/kernel/ucount.c @@ -57,16 +57,23 @@ static struct ctl_table_root set_root = { static int zero = 0; static int int_max = INT_MAX; +#define UCOUNT_ENTRY(name) \ + { \ + .procname = name, \ + .maxlen = sizeof(int), \ + .mode = 0644, \ + .proc_handler = proc_dointvec_minmax, \ + .extra1 = &zero, \ + .extra2 = &int_max, \ + } static struct ctl_table user_table[] = { - { - .procname = "max_user_namespaces", - .data = &init_user_ns.max_user_namespaces, - .maxlen = sizeof(init_user_ns.max_user_namespaces), - .mode = 0644, - .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &int_max, - }, + UCOUNT_ENTRY("max_user_namespaces"), + UCOUNT_ENTRY("max_pid_namespaces"), + UCOUNT_ENTRY("max_uts_namespaces"), + UCOUNT_ENTRY("max_ipc_namespaces"), + UCOUNT_ENTRY("max_net_namespaces"), + UCOUNT_ENTRY("max_mnt_namespaces"), + UCOUNT_ENTRY("max_cgroup_namespaces"), { } }; #endif /* CONFIG_SYSCTL */ @@ -78,8 +85,10 @@ bool setup_userns_sysctls(struct user_namespace *ns) setup_sysctl_set(&ns->set, &set_root, set_is_seen); tbl = kmemdup(user_table, sizeof(user_table), GFP_KERNEL); if (tbl) { - tbl[0].data = &ns->max_user_namespaces; - + int i; + for (i = 0; i < UCOUNT_COUNTS; i++) { + tbl[i].data = &ns->ucount_max[i]; + } ns->sysctls = __register_sysctl_table(&ns->set, "user", tbl); } if (!ns->sysctls) { @@ -172,7 +181,8 @@ static inline bool atomic_inc_below(atomic_t *v, int u) } } -struct ucounts *inc_user_namespaces(struct user_namespace *ns, kuid_t uid) +struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid, + enum ucount_type type) { struct ucounts *ucounts, *iter, *bad; struct user_namespace *tns; @@ -180,31 +190,30 @@ struct ucounts *inc_user_namespaces(struct user_namespace *ns, kuid_t uid) for (iter = ucounts; iter; iter = tns->ucounts) { int max; tns = iter->ns; - max = READ_ONCE(tns->max_user_namespaces); - if (!atomic_inc_below(&iter->user_namespaces, max)) + max = READ_ONCE(tns->ucount_max[type]); + if (!atomic_inc_below(&iter->ucount[type], max)) goto fail; } return ucounts; fail: bad = iter; for (iter = ucounts; iter != bad; iter = iter->ns->ucounts) - atomic_dec(&iter->user_namespaces); + atomic_dec(&iter->ucount[type]); put_ucounts(ucounts); return NULL; } -void dec_user_namespaces(struct ucounts *ucounts) +void dec_ucount(struct ucounts *ucounts, enum ucount_type type) { struct ucounts *iter; for (iter = ucounts; iter; iter = iter->ns->ucounts) { - int dec = atomic_dec_if_positive(&iter->user_namespaces); + int dec = atomic_dec_if_positive(&iter->ucount[type]); WARN_ON_ONCE(dec < 0); } put_ucounts(ucounts); } - static __init int user_namespace_sysctl_init(void) { #ifdef CONFIG_SYSCTL