1dbec2846SEric W. Biederman /* 2dbec2846SEric W. Biederman * This program is free software; you can redistribute it and/or 3dbec2846SEric W. Biederman * modify it under the terms of the GNU General Public License as 4dbec2846SEric W. Biederman * published by the Free Software Foundation, version 2 of the 5dbec2846SEric W. Biederman * License. 6dbec2846SEric W. Biederman */ 7dbec2846SEric W. Biederman 8dbec2846SEric W. Biederman #include <linux/stat.h> 9dbec2846SEric W. Biederman #include <linux/sysctl.h> 10dbec2846SEric W. Biederman #include <linux/slab.h> 11dbec2846SEric W. Biederman #include <linux/user_namespace.h> 12dbec2846SEric W. Biederman 13dbec2846SEric W. Biederman #ifdef CONFIG_SYSCTL 14dbec2846SEric W. Biederman static struct ctl_table_set * 15dbec2846SEric W. Biederman set_lookup(struct ctl_table_root *root) 16dbec2846SEric W. Biederman { 17dbec2846SEric W. Biederman return ¤t_user_ns()->set; 18dbec2846SEric W. Biederman } 19dbec2846SEric W. Biederman 20dbec2846SEric W. Biederman static int set_is_seen(struct ctl_table_set *set) 21dbec2846SEric W. Biederman { 22dbec2846SEric W. Biederman return ¤t_user_ns()->set == set; 23dbec2846SEric W. Biederman } 24dbec2846SEric W. Biederman 25dbec2846SEric W. Biederman static int set_permissions(struct ctl_table_header *head, 26dbec2846SEric W. Biederman struct ctl_table *table) 27dbec2846SEric W. Biederman { 28dbec2846SEric W. Biederman struct user_namespace *user_ns = 29dbec2846SEric W. Biederman container_of(head->set, struct user_namespace, set); 30dbec2846SEric W. Biederman int mode; 31dbec2846SEric W. Biederman 32dbec2846SEric W. Biederman /* Allow users with CAP_SYS_RESOURCE unrestrained access */ 33dbec2846SEric W. Biederman if (ns_capable(user_ns, CAP_SYS_RESOURCE)) 34dbec2846SEric W. Biederman mode = (table->mode & S_IRWXU) >> 6; 35dbec2846SEric W. Biederman else 36dbec2846SEric W. Biederman /* Allow all others at most read-only access */ 37dbec2846SEric W. Biederman mode = table->mode & S_IROTH; 38dbec2846SEric W. Biederman return (mode << 6) | (mode << 3) | mode; 39dbec2846SEric W. Biederman } 40dbec2846SEric W. Biederman 41dbec2846SEric W. Biederman static struct ctl_table_root set_root = { 42dbec2846SEric W. Biederman .lookup = set_lookup, 43dbec2846SEric W. Biederman .permissions = set_permissions, 44dbec2846SEric W. Biederman }; 45dbec2846SEric W. Biederman 46*b376c3e1SEric W. Biederman static int zero = 0; 47*b376c3e1SEric W. Biederman static int int_max = INT_MAX; 48dbec2846SEric W. Biederman static struct ctl_table userns_table[] = { 49*b376c3e1SEric W. Biederman { 50*b376c3e1SEric W. Biederman .procname = "max_user_namespaces", 51*b376c3e1SEric W. Biederman .data = &init_user_ns.max_user_namespaces, 52*b376c3e1SEric W. Biederman .maxlen = sizeof(init_user_ns.max_user_namespaces), 53*b376c3e1SEric W. Biederman .mode = 0644, 54*b376c3e1SEric W. Biederman .proc_handler = proc_dointvec_minmax, 55*b376c3e1SEric W. Biederman .extra1 = &zero, 56*b376c3e1SEric W. Biederman .extra2 = &int_max, 57*b376c3e1SEric W. Biederman }, 58dbec2846SEric W. Biederman { } 59dbec2846SEric W. Biederman }; 60dbec2846SEric W. Biederman #endif /* CONFIG_SYSCTL */ 61dbec2846SEric W. Biederman 62dbec2846SEric W. Biederman bool setup_userns_sysctls(struct user_namespace *ns) 63dbec2846SEric W. Biederman { 64dbec2846SEric W. Biederman #ifdef CONFIG_SYSCTL 65dbec2846SEric W. Biederman struct ctl_table *tbl; 66dbec2846SEric W. Biederman setup_sysctl_set(&ns->set, &set_root, set_is_seen); 67dbec2846SEric W. Biederman tbl = kmemdup(userns_table, sizeof(userns_table), GFP_KERNEL); 68dbec2846SEric W. Biederman if (tbl) { 69*b376c3e1SEric W. Biederman tbl[0].data = &ns->max_user_namespaces; 70*b376c3e1SEric W. Biederman 71dbec2846SEric W. Biederman ns->sysctls = __register_sysctl_table(&ns->set, "userns", tbl); 72dbec2846SEric W. Biederman } 73dbec2846SEric W. Biederman if (!ns->sysctls) { 74dbec2846SEric W. Biederman kfree(tbl); 75dbec2846SEric W. Biederman retire_sysctl_set(&ns->set); 76dbec2846SEric W. Biederman return false; 77dbec2846SEric W. Biederman } 78dbec2846SEric W. Biederman #endif 79dbec2846SEric W. Biederman return true; 80dbec2846SEric W. Biederman } 81dbec2846SEric W. Biederman 82dbec2846SEric W. Biederman void retire_userns_sysctls(struct user_namespace *ns) 83dbec2846SEric W. Biederman { 84dbec2846SEric W. Biederman #ifdef CONFIG_SYSCTL 85dbec2846SEric W. Biederman struct ctl_table *tbl; 86dbec2846SEric W. Biederman 87dbec2846SEric W. Biederman tbl = ns->sysctls->ctl_table_arg; 88dbec2846SEric W. Biederman unregister_sysctl_table(ns->sysctls); 89dbec2846SEric W. Biederman retire_sysctl_set(&ns->set); 90dbec2846SEric W. Biederman kfree(tbl); 91dbec2846SEric W. Biederman #endif 92dbec2846SEric W. Biederman } 93dbec2846SEric W. Biederman 94*b376c3e1SEric W. Biederman static inline bool atomic_inc_below(atomic_t *v, int u) 95*b376c3e1SEric W. Biederman { 96*b376c3e1SEric W. Biederman int c, old; 97*b376c3e1SEric W. Biederman c = atomic_read(v); 98*b376c3e1SEric W. Biederman for (;;) { 99*b376c3e1SEric W. Biederman if (unlikely(c >= u)) 100*b376c3e1SEric W. Biederman return false; 101*b376c3e1SEric W. Biederman old = atomic_cmpxchg(v, c, c+1); 102*b376c3e1SEric W. Biederman if (likely(old == c)) 103*b376c3e1SEric W. Biederman return true; 104*b376c3e1SEric W. Biederman c = old; 105*b376c3e1SEric W. Biederman } 106*b376c3e1SEric W. Biederman } 107*b376c3e1SEric W. Biederman 108*b376c3e1SEric W. Biederman bool inc_user_namespaces(struct user_namespace *ns) 109*b376c3e1SEric W. Biederman { 110*b376c3e1SEric W. Biederman struct user_namespace *pos, *bad; 111*b376c3e1SEric W. Biederman for (pos = ns; pos; pos = pos->parent) { 112*b376c3e1SEric W. Biederman int max = READ_ONCE(pos->max_user_namespaces); 113*b376c3e1SEric W. Biederman if (!atomic_inc_below(&pos->user_namespaces, max)) 114*b376c3e1SEric W. Biederman goto fail; 115*b376c3e1SEric W. Biederman } 116*b376c3e1SEric W. Biederman return true; 117*b376c3e1SEric W. Biederman fail: 118*b376c3e1SEric W. Biederman bad = pos; 119*b376c3e1SEric W. Biederman for (pos = ns; pos != bad; pos = pos->parent) 120*b376c3e1SEric W. Biederman atomic_dec(&pos->user_namespaces); 121*b376c3e1SEric W. Biederman 122*b376c3e1SEric W. Biederman return false; 123*b376c3e1SEric W. Biederman } 124*b376c3e1SEric W. Biederman 125*b376c3e1SEric W. Biederman void dec_user_namespaces(struct user_namespace *ns) 126*b376c3e1SEric W. Biederman { 127*b376c3e1SEric W. Biederman struct user_namespace *pos; 128*b376c3e1SEric W. Biederman for (pos = ns; pos; pos = pos->parent) { 129*b376c3e1SEric W. Biederman int dec = atomic_dec_if_positive(&pos->user_namespaces); 130*b376c3e1SEric W. Biederman WARN_ON_ONCE(dec < 0); 131*b376c3e1SEric W. Biederman } 132*b376c3e1SEric W. Biederman } 133*b376c3e1SEric W. Biederman 134dbec2846SEric W. Biederman static __init int user_namespace_sysctl_init(void) 135dbec2846SEric W. Biederman { 136dbec2846SEric W. Biederman #ifdef CONFIG_SYSCTL 137dbec2846SEric W. Biederman static struct ctl_table_header *userns_header; 138dbec2846SEric W. Biederman static struct ctl_table empty[1]; 139dbec2846SEric W. Biederman /* 140dbec2846SEric W. Biederman * It is necessary to register the userns directory in the 141dbec2846SEric W. Biederman * default set so that registrations in the child sets work 142dbec2846SEric W. Biederman * properly. 143dbec2846SEric W. Biederman */ 144dbec2846SEric W. Biederman userns_header = register_sysctl("userns", empty); 145dbec2846SEric W. Biederman BUG_ON(!userns_header); 146dbec2846SEric W. Biederman BUG_ON(!setup_userns_sysctls(&init_user_ns)); 147dbec2846SEric W. Biederman #endif 148dbec2846SEric W. Biederman return 0; 149dbec2846SEric W. Biederman } 150dbec2846SEric W. Biederman subsys_initcall(user_namespace_sysctl_init); 151dbec2846SEric W. Biederman 152dbec2846SEric W. Biederman 153