On Thu, Aug 11, 2016 at 12:02 AM, Andrei Vagin <avagin@xxxxxxxxxx> wrote: > This patch adds /proc/ucounts where all non-zero ucounts for a current > userns are shown. Eric would have a better sense of this, but I think we would normally avoid putting something in the top-level /proc directory, especially for namespace things (which IIUC usually appear in /proc/$pid/ns/). Also, this should describe what ucounts are for people unfamiliar with them. (i.e. this commit message doesn't really contain a detailed description of what's being added.) And finally, any changes to /proc need an associated entry in Documentation/filesystems/proc.txt > > $ cat /proc/ucounts > user: 1000 1 > net: 1000 1 > mnt: 1000 2 > mnt: 0 10 > cgroup: 0 1 > > There are three columns: type, uid, value. > > Signed-off-by: Andrei Vagin <avagin@xxxxxxxxxx> > --- > kernel/ucount.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 121 insertions(+) > > diff --git a/kernel/ucount.c b/kernel/ucount.c > index 9d20d5d..02a7b7f 100644 > --- a/kernel/ucount.c > +++ b/kernel/ucount.c > @@ -9,6 +9,8 @@ > #include <linux/sysctl.h> > #include <linux/slab.h> > #include <linux/hash.h> > +#include <linux/seq_file.h> > +#include <linux/proc_fs.h> > #include <linux/user_namespace.h> > > #define UCOUNTS_HASHTABLE_BITS 10 > @@ -232,4 +234,123 @@ static __init int user_namespace_sysctl_init(void) > } > subsys_initcall(user_namespace_sysctl_init); > > +#ifdef CONFIG_PROC_FS > +struct ucounts_iterator { > + int hash; > +}; > + > +static void *ucounts_start(struct seq_file *f, loff_t *pos) > +{ > + struct ucounts_iterator *iter = f->private; > + struct user_namespace *ns = current_user_ns(); > + int h, i = 0; > + > + spin_lock(&ucounts_lock); > + for (h = 0; h < (1 << UCOUNTS_HASHTABLE_BITS); h++) { > + struct ucounts *ucounts; > + > + hlist_for_each_entry(ucounts, &ucounts_hashtable[h], node) { > + if (ucounts->ns != ns) > + continue; > + if (i++ < *pos) > + continue; > + > + iter->hash = h; > + > + return ucounts; > + } > + } > + > + return NULL; > +} > + > +static void ucounts_stop(struct seq_file *f, void *v) > +{ > + spin_unlock(&ucounts_lock); > +} I don't see where ucounts_lock is defined, but even still, holding a spinlock across start/stop will provide a way DoS anyone else using that lock. And sparse will yell at you very loudly for the unbalanced locking too. :) > +static void *ucounts_next(struct seq_file *f, void *v, loff_t *pos) > +{ > + struct ucounts_iterator *iter = f->private; > + struct user_namespace *ns = current_user_ns(); > + struct ucounts *ucounts = v; > + int h; > + > + ++*pos; > + > + for (h = iter->hash; h < (1 << UCOUNTS_HASHTABLE_BITS); h++) { > + struct hlist_node *node; > + > + if (ucounts == NULL) { > + node = ucounts_hashtable[h].first; > + iter->hash = h; > + } else > + node = ucounts->node.next; > + > + ucounts = hlist_entry(node, struct ucounts, node); > + > + hlist_for_each_entry_from(ucounts, node) { > + if (ucounts->ns != ns) > + continue; > + > + return ucounts; > + } > + > + ucounts = NULL; > + } > + > + return NULL; > +} > + > +static int ucounts_show(struct seq_file *f, void *v) > +{ > + static const char * const ns_strs[] = { > + "user", "pid", "uts", "ipc", > + "net", "mnt", "cgroup", NULL > + }; > + struct user_namespace *ns = current_user_ns(); > + struct ucounts *ucounts = v; > + uid_t uid; > + int i; > + > + uid = from_kuid_munged(ns, ucounts->uid); > + > + for (i = 0; ns_strs[i]; i++) { > + int val = atomic_read(&ucounts->ucount[i]); > + > + if (val == 0) > + continue; > + > + seq_printf(f, "%s:\t%10u\t%10d\n", ns_strs[i], uid, val); > + } > > + return 0; > +} > + > +static const struct seq_operations ucounts_seq_operations = { > + .start = ucounts_start, > + .next = ucounts_next, > + .stop = ucounts_stop, > + .show = ucounts_show, > +}; > + > +static int ucounts_open(struct inode *inode, struct file *filp) > +{ > + return seq_open_private(filp, &ucounts_seq_operations, > + sizeof(struct ucounts_iterator)); > +} > + > +static const struct file_operations proc_ucounts_operations = { > + .open = ucounts_open, > + .read = seq_read, > + .llseek = seq_lseek, > + .release = seq_release_private, > +}; > + > +static int __init proc_ucounts_init(void) > +{ > + proc_create("ucounts", 0, NULL, &proc_ucounts_operations); > + return 0; > +} > +fs_initcall(proc_ucounts_init); > +#endif /* CONFIG_PROC_FS */ > -- > 2.5.5 > -Kees -- Kees Cook Nexus Security _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/containers