diff options
author | Yordan Karadzhov (VMware) <y.karadz@gmail.com> | 2021-11-02 18:54:01 +0200 |
---|---|---|
committer | Yordan Karadzhov (VMware) <y.karadz@gmail.com> | 2021-11-05 13:53:03 +0200 |
commit | ce65f02585bae7079ca8899fb458fc08c8a46b42 (patch) | |
tree | 0d7f16dbe7710c73395bb0791fe7db55bcd6cba5 | |
parent | cfd7e373390aa16fd766a8f670a9711b5aa74b67 (diff) | |
download | linux-ce65f02585bae7079ca8899fb458fc08c8a46b42.tar.gz |
namespacefs: Couple namespacefs to the UTS namespace
When the UTS namespace gets initialized, a directory called 'uts'
is added to namespacesfs. This directory represents the main UTS
namespace and also serves as a trunk (parent) of all other UTS
namespaces. Every time when a new UTS namespace is created a
corresponding directory is added to 'namespacefs/uts/'. The 'inum'
of the new namespace gives the name of its directory. When a UTS
namespace is destroyed the corresponding directory is removed. Each
directory contains a file called 'uname' that can be used to get the
unique data fields of the uts namespaces(sysname, nodename, ...).
Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
-rw-r--r-- | fs/namespacefs/inode.c | 57 | ||||
-rw-r--r-- | include/linux/namespacefs.h | 15 | ||||
-rw-r--r-- | kernel/utsname.c | 8 |
3 files changed, 79 insertions, 1 deletions
diff --git a/fs/namespacefs/inode.c b/fs/namespacefs/inode.c index 5182ffb5d6f209..7b2570aa28fe03 100644 --- a/fs/namespacefs/inode.c +++ b/fs/namespacefs/inode.c @@ -14,6 +14,7 @@ #include <linux/proc_ns.h> #include <linux/seq_file.h> #include <linux/pid_namespace.h> +#include <linux/utsname.h> #define S_IRALL (S_IRUSR | S_IRGRP | S_IROTH) #define S_IXALL (S_IXUSR | S_IXGRP | S_IXOTH) @@ -316,6 +317,56 @@ void namespacefs_remove_pid_ns_dir(struct pid_namespace *ns) namespacefs_remove_dir(ns->ns.dentry); } +#define _UNAME_N_FIELDS 5 +#define _UNAME_MAX_LEN ((__NEW_UTS_LEN + 2) * _UNAME_MAX_LEN + 1) + +static ssize_t _uts_ns_read(struct file *file, char __user *ubuf, + size_t count, loff_t *pos) +{ + struct new_utsname *name = file->private_data; + char buff[_UNAME_MAX_LEN]; + int n; + + n = snprintf(buff, _UNAME_MAX_LEN, + "%s %s %s %s %s\n", + name->sysname, + name->nodename, + name->release, + name->version, + name->machine); + + return simple_read_from_buffer(ubuf, count, pos, buff, n); +} + +static const struct file_operations uts_fops = { + .open = simple_open, + .read = _uts_ns_read, + .llseek = default_llseek, +}; + +int namespacefs_create_uts_ns_dir(struct uts_namespace *ns) +{ + int err = _create_inod_dir(&ns->ns, init_uts_ns.ns.dentry); + struct dentry *dentry; + + if (err) + return err; + + dentry = namespacefs_create_file("uname", ns->ns.dentry, + &uts_fops, &ns->name); + if (IS_ERR(dentry)) { + dput(ns->ns.dentry); + return PTR_ERR(dentry); + } + + return 0; +} + +void namespacefs_remove_uts_ns_dir(struct uts_namespace *ns) +{ + namespacefs_remove_dir(ns->ns.dentry); +} + static int _add_ns_dentry(struct ns_common *ns) { struct dentry *dentry = namespacefs_create_dir(ns->ops->name, NULL); @@ -340,7 +391,11 @@ static int __init namespacefs_init(void) if (err) goto fail; - err = _add_ns_dentry(&(init_pid_ns.ns)); + err = _add_ns_dentry(&init_pid_ns.ns); + if (err) + goto unreg; + + err = _add_ns_dentry(&init_uts_ns.ns); if (err) goto unreg; diff --git a/include/linux/namespacefs.h b/include/linux/namespacefs.h index 020bf5bbb3b534..67ef60d289795f 100644 --- a/include/linux/namespacefs.h +++ b/include/linux/namespacefs.h @@ -14,6 +14,10 @@ int namespacefs_create_pid_ns_dir(struct pid_namespace *ns); void namespacefs_remove_pid_ns_dir(struct pid_namespace *ns); +int namespacefs_create_uts_ns_dir(struct uts_namespace *ns); + +void namespacefs_remove_uts_ns_dir(struct uts_namespace *ns); + #else static inline int @@ -27,6 +31,17 @@ namespacefs_remove_pid_ns_dir(struct pid_namespace *ns) { } +static inline int +namespacefs_create_uts_ns_dir(struct uts_namespace *ns) +{ + return 0; +} + +static inline void +namespacefs_remove_uts_ns_dir(struct uts_namespace *ns) +{ +} + #endif /* CONFIG_NAMESPACE_FS */ #endif diff --git a/kernel/utsname.c b/kernel/utsname.c index b1ac3ca870f24e..f6f707e5c5333f 100644 --- a/kernel/utsname.c +++ b/kernel/utsname.c @@ -12,6 +12,7 @@ #include <linux/slab.h> #include <linux/cred.h> #include <linux/user_namespace.h> +#include <linux/namespacefs.h> #include <linux/proc_ns.h> #include <linux/sched/task.h> @@ -70,6 +71,11 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns, memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); ns->user_ns = get_user_ns(user_ns); up_read(&uts_sem); + + err = namespacefs_create_uts_ns_dir(ns); + if (err) + goto fail_free; + return ns; fail_free: @@ -105,6 +111,8 @@ struct uts_namespace *copy_utsname(unsigned long flags, void free_uts_ns(struct uts_namespace *ns) { + namespacefs_remove_uts_ns_dir(ns); + dec_uts_namespaces(ns->ucounts); put_user_ns(ns->user_ns); ns_free_inum(&ns->ns); |