LCOV - code coverage report
Current view: top level - kernel - ucount.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 83 154 53.9 %
Date: 2022-12-09 01:23:36 Functions: 10 18 55.6 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : 
       3             : #include <linux/stat.h>
       4             : #include <linux/sysctl.h>
       5             : #include <linux/slab.h>
       6             : #include <linux/cred.h>
       7             : #include <linux/hash.h>
       8             : #include <linux/kmemleak.h>
       9             : #include <linux/user_namespace.h>
      10             : 
      11             : struct ucounts init_ucounts = {
      12             :         .ns    = &init_user_ns,
      13             :         .uid   = GLOBAL_ROOT_UID,
      14             :         .count = ATOMIC_INIT(1),
      15             : };
      16             : 
      17             : #define UCOUNTS_HASHTABLE_BITS 10
      18             : static struct hlist_head ucounts_hashtable[(1 << UCOUNTS_HASHTABLE_BITS)];
      19             : static DEFINE_SPINLOCK(ucounts_lock);
      20             : 
      21             : #define ucounts_hashfn(ns, uid)                                         \
      22             :         hash_long((unsigned long)__kuid_val(uid) + (unsigned long)(ns), \
      23             :                   UCOUNTS_HASHTABLE_BITS)
      24             : #define ucounts_hashentry(ns, uid)      \
      25             :         (ucounts_hashtable + ucounts_hashfn(ns, uid))
      26             : 
      27             : 
      28             : #ifdef CONFIG_SYSCTL
      29             : static struct ctl_table_set *
      30           0 : set_lookup(struct ctl_table_root *root)
      31             : {
      32           0 :         return &current_user_ns()->set;
      33             : }
      34             : 
      35           0 : static int set_is_seen(struct ctl_table_set *set)
      36             : {
      37           0 :         return &current_user_ns()->set == set;
      38             : }
      39             : 
      40           0 : static int set_permissions(struct ctl_table_header *head,
      41             :                                   struct ctl_table *table)
      42             : {
      43           0 :         struct user_namespace *user_ns =
      44           0 :                 container_of(head->set, struct user_namespace, set);
      45             :         int mode;
      46             : 
      47             :         /* Allow users with CAP_SYS_RESOURCE unrestrained access */
      48           0 :         if (ns_capable(user_ns, CAP_SYS_RESOURCE))
      49           0 :                 mode = (table->mode & S_IRWXU) >> 6;
      50             :         else
      51             :         /* Allow all others at most read-only access */
      52           0 :                 mode = table->mode & S_IROTH;
      53           0 :         return (mode << 6) | (mode << 3) | mode;
      54             : }
      55             : 
      56             : static struct ctl_table_root set_root = {
      57             :         .lookup = set_lookup,
      58             :         .permissions = set_permissions,
      59             : };
      60             : 
      61             : static long ue_zero = 0;
      62             : static long ue_int_max = INT_MAX;
      63             : 
      64             : #define UCOUNT_ENTRY(name)                                      \
      65             :         {                                                       \
      66             :                 .procname       = name,                         \
      67             :                 .maxlen         = sizeof(long),                 \
      68             :                 .mode           = 0644,                         \
      69             :                 .proc_handler   = proc_doulongvec_minmax,       \
      70             :                 .extra1         = &ue_zero,                 \
      71             :                 .extra2         = &ue_int_max,                      \
      72             :         }
      73             : static struct ctl_table user_table[] = {
      74             :         UCOUNT_ENTRY("max_user_namespaces"),
      75             :         UCOUNT_ENTRY("max_pid_namespaces"),
      76             :         UCOUNT_ENTRY("max_uts_namespaces"),
      77             :         UCOUNT_ENTRY("max_ipc_namespaces"),
      78             :         UCOUNT_ENTRY("max_net_namespaces"),
      79             :         UCOUNT_ENTRY("max_mnt_namespaces"),
      80             :         UCOUNT_ENTRY("max_cgroup_namespaces"),
      81             :         UCOUNT_ENTRY("max_time_namespaces"),
      82             : #ifdef CONFIG_INOTIFY_USER
      83             :         UCOUNT_ENTRY("max_inotify_instances"),
      84             :         UCOUNT_ENTRY("max_inotify_watches"),
      85             : #endif
      86             : #ifdef CONFIG_FANOTIFY
      87             :         UCOUNT_ENTRY("max_fanotify_groups"),
      88             :         UCOUNT_ENTRY("max_fanotify_marks"),
      89             : #endif
      90             :         { },
      91             :         { },
      92             :         { },
      93             :         { },
      94             :         { }
      95             : };
      96             : #endif /* CONFIG_SYSCTL */
      97             : 
      98           1 : bool setup_userns_sysctls(struct user_namespace *ns)
      99             : {
     100             : #ifdef CONFIG_SYSCTL
     101             :         struct ctl_table *tbl;
     102             : 
     103             :         BUILD_BUG_ON(ARRAY_SIZE(user_table) != UCOUNT_COUNTS + 1);
     104           1 :         setup_sysctl_set(&ns->set, &set_root, set_is_seen);
     105           1 :         tbl = kmemdup(user_table, sizeof(user_table), GFP_KERNEL);
     106           1 :         if (tbl) {
     107             :                 int i;
     108          14 :                 for (i = 0; i < UCOUNT_COUNTS; i++) {
     109          14 :                         tbl[i].data = &ns->ucount_max[i];
     110             :                 }
     111           1 :                 ns->sysctls = __register_sysctl_table(&ns->set, "user", tbl);
     112             :         }
     113           1 :         if (!ns->sysctls) {
     114           0 :                 kfree(tbl);
     115           0 :                 retire_sysctl_set(&ns->set);
     116           0 :                 return false;
     117             :         }
     118             : #endif
     119             :         return true;
     120             : }
     121             : 
     122           0 : void retire_userns_sysctls(struct user_namespace *ns)
     123             : {
     124             : #ifdef CONFIG_SYSCTL
     125             :         struct ctl_table *tbl;
     126             : 
     127           0 :         tbl = ns->sysctls->ctl_table_arg;
     128           0 :         unregister_sysctl_table(ns->sysctls);
     129           0 :         retire_sysctl_set(&ns->set);
     130           0 :         kfree(tbl);
     131             : #endif
     132           0 : }
     133             : 
     134             : static struct ucounts *find_ucounts(struct user_namespace *ns, kuid_t uid, struct hlist_head *hashent)
     135             : {
     136             :         struct ucounts *ucounts;
     137             : 
     138           2 :         hlist_for_each_entry(ucounts, hashent, node) {
     139           0 :                 if (uid_eq(ucounts->uid, uid) && (ucounts->ns == ns))
     140             :                         return ucounts;
     141             :         }
     142             :         return NULL;
     143             : }
     144             : 
     145           1 : static void hlist_add_ucounts(struct ucounts *ucounts)
     146             : {
     147           2 :         struct hlist_head *hashent = ucounts_hashentry(ucounts->ns, ucounts->uid);
     148           1 :         spin_lock_irq(&ucounts_lock);
     149           2 :         hlist_add_head(&ucounts->node, hashent);
     150           1 :         spin_unlock_irq(&ucounts_lock);
     151           1 : }
     152             : 
     153             : static inline bool get_ucounts_or_wrap(struct ucounts *ucounts)
     154             : {
     155             :         /* Returns true on a successful get, false if the count wraps. */
     156         214 :         return !atomic_add_negative(1, &ucounts->count);
     157             : }
     158             : 
     159         107 : struct ucounts *get_ucounts(struct ucounts *ucounts)
     160             : {
     161         107 :         if (!get_ucounts_or_wrap(ucounts)) {
     162           0 :                 put_ucounts(ucounts);
     163           0 :                 ucounts = NULL;
     164             :         }
     165         107 :         return ucounts;
     166             : }
     167             : 
     168           1 : struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid)
     169             : {
     170           2 :         struct hlist_head *hashent = ucounts_hashentry(ns, uid);
     171             :         struct ucounts *ucounts, *new;
     172             :         bool wrapped;
     173             : 
     174           1 :         spin_lock_irq(&ucounts_lock);
     175           1 :         ucounts = find_ucounts(ns, uid, hashent);
     176           1 :         if (!ucounts) {
     177           1 :                 spin_unlock_irq(&ucounts_lock);
     178             : 
     179           1 :                 new = kzalloc(sizeof(*new), GFP_KERNEL);
     180           1 :                 if (!new)
     181             :                         return NULL;
     182             : 
     183           1 :                 new->ns = ns;
     184           1 :                 new->uid = uid;
     185           2 :                 atomic_set(&new->count, 1);
     186             : 
     187           1 :                 spin_lock_irq(&ucounts_lock);
     188           1 :                 ucounts = find_ucounts(ns, uid, hashent);
     189           1 :                 if (ucounts) {
     190           0 :                         kfree(new);
     191             :                 } else {
     192           2 :                         hlist_add_head(&new->node, hashent);
     193           1 :                         get_user_ns(new->ns);
     194           1 :                         spin_unlock_irq(&ucounts_lock);
     195           1 :                         return new;
     196             :                 }
     197             :         }
     198           0 :         wrapped = !get_ucounts_or_wrap(ucounts);
     199           0 :         spin_unlock_irq(&ucounts_lock);
     200           0 :         if (wrapped) {
     201           0 :                 put_ucounts(ucounts);
     202           0 :                 return NULL;
     203             :         }
     204             :         return ucounts;
     205             : }
     206             : 
     207          92 : void put_ucounts(struct ucounts *ucounts)
     208             : {
     209             :         unsigned long flags;
     210             : 
     211          92 :         if (atomic_dec_and_lock_irqsave(&ucounts->count, &ucounts_lock, flags)) {
     212           0 :                 hlist_del_init(&ucounts->node);
     213           0 :                 spin_unlock_irqrestore(&ucounts_lock, flags);
     214           0 :                 put_user_ns(ucounts->ns);
     215           0 :                 kfree(ucounts);
     216             :         }
     217          92 : }
     218             : 
     219             : static inline bool atomic_long_inc_below(atomic_long_t *v, int u)
     220             : {
     221             :         long c, old;
     222           1 :         c = atomic_long_read(v);
     223             :         for (;;) {
     224           1 :                 if (unlikely(c >= u))
     225             :                         return false;
     226           2 :                 old = atomic_long_cmpxchg(v, c, c+1);
     227           1 :                 if (likely(old == c))
     228             :                         return true;
     229             :                 c = old;
     230             :         }
     231             : }
     232             : 
     233           1 : struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid,
     234             :                            enum ucount_type type)
     235             : {
     236             :         struct ucounts *ucounts, *iter, *bad;
     237             :         struct user_namespace *tns;
     238           1 :         ucounts = alloc_ucounts(ns, uid);
     239           2 :         for (iter = ucounts; iter; iter = tns->ucounts) {
     240             :                 long max;
     241           1 :                 tns = iter->ns;
     242           1 :                 max = READ_ONCE(tns->ucount_max[type]);
     243           2 :                 if (!atomic_long_inc_below(&iter->ucount[type], max))
     244             :                         goto fail;
     245             :         }
     246             :         return ucounts;
     247             : fail:
     248             :         bad = iter;
     249           0 :         for (iter = ucounts; iter != bad; iter = iter->ns->ucounts)
     250           0 :                 atomic_long_dec(&iter->ucount[type]);
     251             : 
     252           0 :         put_ucounts(ucounts);
     253           0 :         return NULL;
     254             : }
     255             : 
     256           0 : void dec_ucount(struct ucounts *ucounts, enum ucount_type type)
     257             : {
     258             :         struct ucounts *iter;
     259           0 :         for (iter = ucounts; iter; iter = iter->ns->ucounts) {
     260           0 :                 long dec = atomic_long_dec_if_positive(&iter->ucount[type]);
     261           0 :                 WARN_ON_ONCE(dec < 0);
     262             :         }
     263           0 :         put_ucounts(ucounts);
     264           0 : }
     265             : 
     266         107 : long inc_rlimit_ucounts(struct ucounts *ucounts, enum ucount_type type, long v)
     267             : {
     268             :         struct ucounts *iter;
     269         108 :         long max = LONG_MAX;
     270         108 :         long ret = 0;
     271             : 
     272         216 :         for (iter = ucounts; iter; iter = iter->ns->ucounts) {
     273         216 :                 long new = atomic_long_add_return(v, &iter->ucount[type]);
     274         107 :                 if (new < 0 || new > max)
     275             :                         ret = LONG_MAX;
     276         107 :                 else if (iter == ucounts)
     277         107 :                         ret = new;
     278         108 :                 max = READ_ONCE(iter->ns->ucount_max[type]);
     279             :         }
     280         107 :         return ret;
     281             : }
     282             : 
     283          93 : bool dec_rlimit_ucounts(struct ucounts *ucounts, enum ucount_type type, long v)
     284             : {
     285             :         struct ucounts *iter;
     286          93 :         long new = -1; /* Silence compiler warning */
     287         186 :         for (iter = ucounts; iter; iter = iter->ns->ucounts) {
     288         186 :                 long dec = atomic_long_sub_return(v, &iter->ucount[type]);
     289          93 :                 WARN_ON_ONCE(dec < 0);
     290          93 :                 if (iter == ucounts)
     291          93 :                         new = dec;
     292             :         }
     293          93 :         return (new == 0);
     294             : }
     295             : 
     296           0 : static void do_dec_rlimit_put_ucounts(struct ucounts *ucounts,
     297             :                                 struct ucounts *last, enum ucount_type type)
     298             : {
     299             :         struct ucounts *iter, *next;
     300           0 :         for (iter = ucounts; iter != last; iter = next) {
     301           0 :                 long dec = atomic_long_sub_return(1, &iter->ucount[type]);
     302           0 :                 WARN_ON_ONCE(dec < 0);
     303           0 :                 next = iter->ns->ucounts;
     304           0 :                 if (dec == 0)
     305           0 :                         put_ucounts(iter);
     306             :         }
     307           0 : }
     308             : 
     309           0 : void dec_rlimit_put_ucounts(struct ucounts *ucounts, enum ucount_type type)
     310             : {
     311           0 :         do_dec_rlimit_put_ucounts(ucounts, NULL, type);
     312           0 : }
     313             : 
     314           0 : long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type)
     315             : {
     316             :         /* Caller must hold a reference to ucounts */
     317             :         struct ucounts *iter;
     318           0 :         long max = LONG_MAX;
     319           0 :         long dec, ret = 0;
     320             : 
     321           0 :         for (iter = ucounts; iter; iter = iter->ns->ucounts) {
     322           0 :                 long new = atomic_long_add_return(1, &iter->ucount[type]);
     323           0 :                 if (new < 0 || new > max)
     324             :                         goto unwind;
     325           0 :                 if (iter == ucounts)
     326           0 :                         ret = new;
     327           0 :                 max = READ_ONCE(iter->ns->ucount_max[type]);
     328             :                 /*
     329             :                  * Grab an extra ucount reference for the caller when
     330             :                  * the rlimit count was previously 0.
     331             :                  */
     332           0 :                 if (new != 1)
     333           0 :                         continue;
     334           0 :                 if (!get_ucounts(iter))
     335             :                         goto dec_unwind;
     336             :         }
     337             :         return ret;
     338             : dec_unwind:
     339           0 :         dec = atomic_long_sub_return(1, &iter->ucount[type]);
     340           0 :         WARN_ON_ONCE(dec < 0);
     341             : unwind:
     342           0 :         do_dec_rlimit_put_ucounts(ucounts, iter, type);
     343           0 :         return 0;
     344             : }
     345             : 
     346         107 : bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsigned long rlimit)
     347             : {
     348             :         struct ucounts *iter;
     349         107 :         long max = rlimit;
     350         107 :         if (rlimit > LONG_MAX)
     351           0 :                 max = LONG_MAX;
     352         107 :         for (iter = ucounts; iter; iter = iter->ns->ucounts) {
     353         107 :                 long val = get_ucounts_value(iter, type);
     354         107 :                 if (val < 0 || val > max)
     355             :                         return true;
     356         107 :                 max = READ_ONCE(iter->ns->ucount_max[type]);
     357             :         }
     358             :         return false;
     359             : }
     360             : 
     361           1 : static __init int user_namespace_sysctl_init(void)
     362             : {
     363             : #ifdef CONFIG_SYSCTL
     364             :         static struct ctl_table_header *user_header;
     365             :         static struct ctl_table empty[1];
     366             :         /*
     367             :          * It is necessary to register the user directory in the
     368             :          * default set so that registrations in the child sets work
     369             :          * properly.
     370             :          */
     371           1 :         user_header = register_sysctl("user", empty);
     372           1 :         kmemleak_ignore(user_header);
     373           1 :         BUG_ON(!user_header);
     374           1 :         BUG_ON(!setup_userns_sysctls(&init_user_ns));
     375             : #endif
     376           1 :         hlist_add_ucounts(&init_ucounts);
     377           1 :         inc_rlimit_ucounts(&init_ucounts, UCOUNT_RLIMIT_NPROC, 1);
     378           1 :         return 0;
     379             : }
     380             : subsys_initcall(user_namespace_sysctl_init);

Generated by: LCOV version 1.14