[PATCH v4 11/11] smack: documentation for the Smack namespace

2015-10-14 Thread Lukasz Pawelczyk
Adds Documentation/smack-namespace.txt.

Signed-off-by: Lukasz Pawelczyk <l.pawelc...@samsung.com>
Reviewed-by: Casey Schaufler <ca...@schaufler-ca.com>
---
 Documentation/security/00-INDEX|   2 +
 Documentation/security/Smack-namespace.txt | 231 +
 MAINTAINERS|   1 +
 security/smack/Kconfig |   2 +
 4 files changed, 236 insertions(+)
 create mode 100644 Documentation/security/Smack-namespace.txt

diff --git a/Documentation/security/00-INDEX b/Documentation/security/00-INDEX
index 45c82fd..c03a220 100644
--- a/Documentation/security/00-INDEX
+++ b/Documentation/security/00-INDEX
@@ -6,6 +6,8 @@ SELinux.txt
- how to get started with the SELinux security enhancement.
 Smack.txt
- documentation on the Smack Linux Security Module.
+Smack-namespace.txt
+   - documentation on the Smack namespace implementation.
 Yama.txt
- documentation on the Yama Linux Security Module.
 apparmor.txt
diff --git a/Documentation/security/Smack-namespace.txt 
b/Documentation/security/Smack-namespace.txt
new file mode 100644
index 000..5304355
--- /dev/null
+++ b/Documentation/security/Smack-namespace.txt
@@ -0,0 +1,231 @@
+
+  "Quis custodiet ipsos custodes?"
+ - Satires of Juvenal
+
+
+--- What is a Smack namespace ---
+
+Smack namespace was developed to make it possible for Smack to work
+nicely with Linux containers where there is a full operating system
+with its own init inside the namespace. Such a system working with
+Smack expects to have at least partially working SMACK_MAC_ADMIN to be
+able to change labels of processes and files. This is required to be
+able to securely start applications under the control of Smack and
+manage their access rights.
+
+It was implemented using new LSM hooks added to the user namespace
+that were developed together with Smack namespace.
+
+
+--- Design ideas ---
+
+"Smack namespace" is rather "Smack labels namespace" as not the whole
+MAC is namespaced, only the labels. There is a great analogy between
+Smack labels namespace and the user namespace part that remaps UIDs.
+
+The idea is to create a map of labels for a namespace so the namespace
+is only allowed to use those labels. Smack rules are always the same
+as in the init namespace (limited only by what labels are mapped) and
+cannot be manipulated from the child namespace. The map is actually
+only for labels' names. The underlying structures for labels remain
+the same. The filesystem also stores the "unmapped" labels from the
+init namespace.
+
+Let's say we have those labels in the init namespace:
+label1
+label2
+label3
+
+and those rules:
+label1 label2 rwx
+label1 label3 rwx
+label2 label3 rwx
+
+We create a map for a namespace:
+label1 -> mapped1
+label2 -> mapped2
+
+This means that 'label3' is completely invisible in the namespace. As if
+it didn't exist. All the rules that include it are ignored.
+
+Effectively in the namespace we have only one rule:
+mapped1 mapped2 rwx
+
+Which in reality is:
+label1 label2 rwx
+
+All requests to access an object with a 'label3' will be denied. If it
+ever comes to a situation where 'label3' would have to be printed
+(e.g. reading an exec or mmap label from a file to which we have
+access) then huh sign '?' will be printed instead.
+
+All the operations in the namespace on the remaining labels will have
+to be performed using their mapped names. Things like changing own
+process's label, changing filesystem label. Labels will also be
+printed with their mapped names.
+
+You cannot import new labels in a namespace. Every operation that
+would do so in an init namespace will return an error in the child
+namespace. You cannot assign an unmapped or not existing label to an
+object. You can only operate on labels that have been explicitly
+mapped.
+
+
+--- Capabilities ---
+
+Enabling Smack related capabilities (CAP_MAC_ADMIN and
+CAP_MAC_OVERRIDE) is main goal of Smack namespace, so it can work
+properly in the container. And those capabilities do work to some
+extent. In several places where capabilities are checked compatibility
+with Smack namespace has been introduced. Capabilities are of course
+limited to operate only on mapped labels.
+
+CAP_MAC_OVERRIDE works fully, will allow you to ignore Smack access
+rules, but only between objects that have labels mapped. So in the
+example above having this CAP will allow e.g. label2 to write to
+label1, but will not allow any access to label3.
+
+With CAP_MAC_ADMIN the following operations has been allowed inside
+the namespace:
+- setting and removing xattr on files, including the security.* ones
+- setting process's own label (/proc/self/attr/current)
+- mounting in a privileged Smack mode, which means one can specify
+  additional mount options like: smackfsdef, smackfsfloor et

[PATCH v4 02/11] lsm: /proc/$PID/attr/label_map file and getprocattr_seq hook

2015-10-14 Thread Lukasz Pawelczyk
This commit adds a new proc attribute, label_map that is required by an
upcoming Smack namespace. In general it can be used to hold a map of
labels, e.g. to be used in namespaces.

Due to the nature of this file, the standard getprocattr hook might not
be enough to handle it. The map's output can in principle be greater
than page size to which the aforementioned hook is limited.
To handle this properly a getprocattr_seq LSM hook has been added that
makes it possible to handle any chosen proc attr by seq operations.

See the documentation in the patch below for the details about how to
use the hook.

Signed-off-by: Lukasz Pawelczyk <l.pawelc...@samsung.com>
Acked-by: Serge Hallyn <serge.hal...@canonical.com>
---
 fs/proc/base.c| 81 +++
 include/linux/lsm_hooks.h | 15 +
 include/linux/security.h  |  9 ++
 security/security.c   |  8 +
 4 files changed, 107 insertions(+), 6 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index b25eee4..9ec88b8 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2327,20 +2327,77 @@ out:
 }
 
 #ifdef CONFIG_SECURITY
+static int proc_pid_attr_open(struct inode *inode, struct file *file)
+{
+   const char *name = file->f_path.dentry->d_name.name;
+   const struct seq_operations *ops;
+   struct task_struct *task;
+   struct seq_file *seq;
+   int ret;
+
+   file->private_data = NULL;
+
+   task = get_proc_task(inode);
+   if (!task)
+   return -ESRCH;
+
+   /* don't use seq_ops if they are not provided by LSM */
+   ret = security_getprocattr_seq(task, name, );
+   if (ret == -EOPNOTSUPP) {
+   ret = 0;
+   goto put_task;
+   }
+   if (ret)
+   goto put_task;
+
+   ret = seq_open(file, ops);
+   if (ret)
+   goto put_task;
+
+   seq = file->private_data;
+   seq->private = task;
+
+   return 0;
+
+put_task:
+   put_task_struct(task);
+   return ret;
+}
+
+static int proc_pid_attr_release(struct inode *inode, struct file *file)
+{
+   struct seq_file *seq;
+   struct task_struct *task;
+
+   /* don't use seq_ops if they were not provided by LSM */
+   if (file->private_data == NULL)
+   return 0;
+
+   seq = file->private_data;
+   task = seq->private;
+   put_task_struct(task);
+
+   return seq_release(inode, file);
+}
+
 static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
  size_t count, loff_t *ppos)
 {
-   struct inode * inode = file_inode(file);
+   struct inode *inode = file_inode(file);
+   const char *name = file->f_path.dentry->d_name.name;
char *p = NULL;
ssize_t length;
-   struct task_struct *task = get_proc_task(inode);
+   struct task_struct *task;
 
+   /* use seq_ops if they were provided by LSM */
+   if (file->private_data)
+   return seq_read(file, buf, count, ppos);
+
+   task = get_proc_task(inode);
if (!task)
return -ESRCH;
 
-   length = security_getprocattr(task,
- (char*)file->f_path.dentry->d_name.name,
- );
+   length = security_getprocattr(task, (char *)name, );
put_task_struct(task);
if (length > 0)
length = simple_read_from_buffer(buf, count, ppos, p, length);
@@ -2348,6 +2405,15 @@ static ssize_t proc_pid_attr_read(struct file * file, 
char __user * buf,
return length;
 }
 
+static loff_t proc_pid_attr_lseek(struct file *file, loff_t offset, int whence)
+{
+   /* use seq_ops if they were provided by LSM */
+   if (file->private_data)
+   return seq_lseek(file, offset, whence);
+
+   return generic_file_llseek(file, offset, whence);
+}
+
 static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
   size_t count, loff_t *ppos)
 {
@@ -2394,9 +2460,11 @@ out_no_task:
 }
 
 static const struct file_operations proc_pid_attr_operations = {
+   .open   = proc_pid_attr_open,
+   .release= proc_pid_attr_release,
.read   = proc_pid_attr_read,
+   .llseek = proc_pid_attr_lseek,
.write  = proc_pid_attr_write,
-   .llseek = generic_file_llseek,
 };
 
 static const struct pid_entry attr_dir_stuff[] = {
@@ -2406,6 +2474,7 @@ static const struct pid_entry attr_dir_stuff[] = {
REG("fscreate",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
REG("keycreate",  S_IRUGO|S_IWUGO, proc_pid_attr_operations),
REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
+   REG("label_map",  S_IRUGO|S_IWUGO, proc_pid_attr_operations),
 };
 
 static int proc_attr_dir_readdir(s

[PATCH v4 06/11] smack: don't use implicit star to display smackfs/syslog

2015-10-14 Thread Lukasz Pawelczyk
Smackfs/syslog is analogous to onlycap and unconfined. When not filled
they don't do anything. In such cases onlycap and unconfined displayed
nothing when read, but syslog unconditionally displayed star. This
doesn't work well with namespaces where the star could have been
unmapped. Besides the meaning of this star was different then a star
that could be written to this file. This was misleading.

This also brings syslog read/write functions on par with onlycap and
unconfined where it is possible to reset the value to NULL as should be
possible according to comment in smackfs.c describing smack_syslog_label
variable.

Before that the initial state was to allow (smack_syslog_label was
NULL), but after writing star to it the current had to be labeled star
as well to have an access, even thought reading the smackfs/syslog
returned the same result in both cases.

Signed-off-by: Lukasz Pawelczyk <l.pawelc...@samsung.com>
Acked-by: Serge Hallyn <serge.hal...@canonical.com>
---
 security/smack/smackfs.c | 42 +++---
 1 file changed, 27 insertions(+), 15 deletions(-)

diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index ce8d503..05e09ee2 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -2634,23 +2634,20 @@ static const struct file_operations smk_change_rule_ops 
= {
 static ssize_t smk_read_syslog(struct file *filp, char __user *buf,
size_t cn, loff_t *ppos)
 {
-   struct smack_known *skp;
+   char *smack = "";
ssize_t rc = -EINVAL;
int asize;
 
if (*ppos != 0)
return 0;
 
-   if (smack_syslog_label == NULL)
-   skp = _known_star;
-   else
-   skp = smack_syslog_label;
+   if (smack_syslog_label != NULL)
+   smack = smack_syslog_label->smk_known;
 
-   asize = strlen(skp->smk_known) + 1;
+   asize = strlen(smack) + 1;
 
if (cn >= asize)
-   rc = simple_read_from_buffer(buf, cn, ppos, skp->smk_known,
-   asize);
+   rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
 
return rc;
 }
@@ -2678,16 +2675,31 @@ static ssize_t smk_write_syslog(struct file *file, 
const char __user *buf,
if (data == NULL)
return -ENOMEM;
 
-   if (copy_from_user(data, buf, count) != 0)
+   if (copy_from_user(data, buf, count) != 0) {
rc = -EFAULT;
-   else {
-   skp = smk_import_entry(data, count);
-   if (IS_ERR(skp))
-   rc = PTR_ERR(skp);
-   else
-   smack_syslog_label = skp;
+   goto freeout;
}
 
+   /*
+* Clear the smack_syslog_label on invalid label errors. This means
+* that we can pass a null string to unset the syslog value.
+*
+* Importing will also reject a label beginning with '-',
+* so "-syslog" will also work.
+*
+* But do so only on invalid label, not on system errors.
+*/
+   skp = smk_import_entry(data, count);
+   if (PTR_ERR(skp) == -EINVAL)
+   skp = NULL;
+   else if (IS_ERR(skp)) {
+   rc = PTR_ERR(skp);
+   goto freeout;
+   }
+
+   smack_syslog_label = skp;
+
+freeout:
kfree(data);
return rc;
 }
-- 
2.4.3

___
Selinux mailing list
Selinux@tycho.nsa.gov
To unsubscribe, send email to selinux-le...@tycho.nsa.gov.
To get help, send an email containing "help" to selinux-requ...@tycho.nsa.gov.


[PATCH v4 10/11] smack: namespace implementation

2015-10-14 Thread Lukasz Pawelczyk
This commit uses all the changes introduced in "namespace groundwork"
and previous preparation patches and makes smack aware of its namespace
and mapped labels.

It modifies the following functions to be namespace aware:
- smk_access
- smk_find_label_name
- smk_get_label

And all functions that use them (e.g. smk_tskacc).

It also adds another function that is used throughout Smack LSM hooks:
- smk_labels_valid - it checks whether both, subject and object labels
  are properly mapped in a namespace where they are to be used. This
  function is used mostly together with a capability check when there is
  no proper access check that usually checks for that.

All the Smack LSM hooks have been adapted to be namespace aware.

The capabilities (CAP_MAC_ADMIN, CAP_MAC_OVERRIDE) has been allowed in
the namespace for few cases. Check the documentation for the details.

Signed-off-by: Lukasz Pawelczyk <l.pawelc...@samsung.com>
Reviewed-by: Casey Schaufler <ca...@schaufler-ca.com>
---
 security/smack/smack.h|  29 +++-
 security/smack/smack_access.c | 109 ++--
 security/smack/smack_lsm.c| 390 ++
 security/smack/smack_ns.c |  39 +
 security/smack/smackfs.c  |  63 ---
 5 files changed, 483 insertions(+), 147 deletions(-)

diff --git a/security/smack/smack.h b/security/smack/smack.h
index 4b7489f..3d432f4 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -119,6 +119,7 @@ struct superblock_smack {
struct smack_known  *smk_floor;
struct smack_known  *smk_hat;
struct smack_known  *smk_default;
+   struct user_namespace   *smk_ns;
int smk_initialized;
 };
 
@@ -126,6 +127,7 @@ struct socket_smack {
struct smack_known  *smk_out;   /* outbound label */
struct smack_known  *smk_in;/* inbound label */
struct smack_known  *smk_packet;/* TCP peer label */
+   struct user_namespace   *smk_ns;/* user namespace */
 };
 
 /*
@@ -146,6 +148,14 @@ struct task_smack {
struct mutexsmk_rules_lock; /* lock for the rules */
 };
 
+/*
+ * Used for IPC objects (sem, shm, etc)
+ */
+struct ipc_smack {
+   struct smack_known  *smk_known; /* label for access control */
+   struct user_namespace   *smk_ns;/* user namespace */
+};
+
 #defineSMK_INODE_INSTANT   0x01/* inode is instantiated */
 #defineSMK_INODE_TRANSMUTE 0x02/* directory is transmuting */
 #defineSMK_INODE_CHANGED   0x04/* smack was transmuted */
@@ -319,10 +329,11 @@ struct smk_audit_info {
  */
 int smk_access_entry(char *, char *, struct list_head *);
 int smk_access(struct smack_known *, struct smack_known *,
-  int, struct smk_audit_info *);
+  struct user_namespace *, int, struct smk_audit_info *);
 int smk_tskacc(struct task_struct *, struct smack_known *,
+  struct user_namespace *, u32, struct smk_audit_info *);
+int smk_curacc(struct smack_known *, struct user_namespace *,
   u32, struct smk_audit_info *);
-int smk_curacc(struct smack_known *, u32, struct smk_audit_info *);
 struct smack_known *smack_from_secid(const u32);
 char *smk_parse_smack(const char *string, int len, bool *allocated);
 int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
@@ -335,8 +346,9 @@ int smack_has_ns_privilege(struct task_struct *task,
 int smack_has_privilege(struct task_struct *task, int cap);
 int smack_ns_privileged(struct user_namespace *user_ns, int cap);
 int smack_privileged(int cap);
-char *smk_find_label_name(struct smack_known *skp);
-struct smack_known *smk_get_label(const char *string, int len, bool import);
+char *smk_find_label_name(struct smack_known *skp, struct user_namespace *ns);
+struct smack_known *smk_get_label(const char *string, int len, bool import,
+ struct user_namespace *ns);
 
 /*
  * These functions are in smack_ns.c
@@ -350,6 +362,15 @@ struct smack_known *smk_find_unmapped(const char *string, 
int len,
 extern const struct seq_operations proc_label_map_seq_operations;
 ssize_t proc_label_map_write(struct task_struct *p, const struct cred *f_cred,
 void *value, size_t size);
+bool smk_labels_valid(struct smack_known *sbj, struct smack_known *obj,
+ struct user_namespace *ns);
+#else
+static inline bool smk_labels_valid(struct smack_known *sbj,
+   struct smack_known *obj,
+   struct user_namespace *ns)
+{
+   return true;
+}
 #endif /* CONFIG_SECURITY_SMACK_NS */
 
 /*
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 17b7e2c..e230948 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 #inclu

[PATCH v4 04/11] lsm: inode_pre_setxattr hook

2015-10-14 Thread Lukasz Pawelczyk
Add a new LSM hook called before inode's setxattr. It is required for
LSM to be able to reliably replace the xattr's value to be set to
filesystem in __vfs_setxattr_noperm(). Useful for mapped values, like in
the upcoming Smack namespace patches.

Signed-off-by: Lukasz Pawelczyk <l.pawelc...@samsung.com>
Acked-by: Serge Hallyn <serge.hal...@canonical.com>
---
 fs/xattr.c| 10 ++
 include/linux/lsm_hooks.h |  9 +
 include/linux/security.h  | 10 ++
 security/security.c   | 12 
 4 files changed, 41 insertions(+)

diff --git a/fs/xattr.c b/fs/xattr.c
index 072fee1..cbc8d19 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -100,12 +100,22 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const 
char *name,
if (issec)
inode->i_flags &= ~S_NOSEC;
if (inode->i_op->setxattr) {
+   bool alloc = false;
+
+   error = security_inode_pre_setxattr(dentry, name, ,
+   , flags, );
+   if (error)
+   return error;
+
error = inode->i_op->setxattr(dentry, name, value, size, flags);
if (!error) {
fsnotify_xattr(dentry);
security_inode_post_setxattr(dentry, name, value,
 size, flags);
}
+
+   if (alloc)
+   kfree(value);
} else if (issec) {
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
error = security_inode_setsecurity(inode, suffix, value,
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 4f16640..85bfdde 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -349,6 +349,11 @@
  * Check permission before setting the extended attributes
  * @value identified by @name for @dentry.
  * Return 0 if permission is granted.
+ * @inode_pre_setxattr:
+ * Be able to do some operation before setting the @value identified
+ * by @name on the filesystem. Replacing the @value and its @size is
+ * possible. Useful for mapped values. Set @alloc to true if @value
+ * needs to be kfreed afterwards.
  * @inode_post_setxattr:
  * Update inode security field after successful setxattr operation.
  * @value identified by @name for @dentry.
@@ -1448,6 +1453,9 @@ union security_list_options {
int (*inode_getattr)(const struct path *path);
int (*inode_setxattr)(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags);
+   int (*inode_pre_setxattr)(struct dentry *dentry, const char *name,
+ const void **value, size_t *size,
+ int flags, bool *alloc);
void (*inode_post_setxattr)(struct dentry *dentry, const char *name,
const void *value, size_t size,
int flags);
@@ -1730,6 +1738,7 @@ struct security_hook_heads {
struct list_head inode_setattr;
struct list_head inode_getattr;
struct list_head inode_setxattr;
+   struct list_head inode_pre_setxattr;
struct list_head inode_post_setxattr;
struct list_head inode_getxattr;
struct list_head inode_listxattr;
diff --git a/include/linux/security.h b/include/linux/security.h
index 12bd011..4de4865 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -263,6 +263,9 @@ int security_inode_setattr(struct dentry *dentry, struct 
iattr *attr);
 int security_inode_getattr(const struct path *path);
 int security_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags);
+int security_inode_pre_setxattr(struct dentry *dentry, const char *name,
+   const void **value, size_t *size, int flags,
+   bool *alloc);
 void security_inode_post_setxattr(struct dentry *dentry, const char *name,
  const void *value, size_t size, int flags);
 int security_inode_getxattr(struct dentry *dentry, const char *name);
@@ -691,6 +694,13 @@ static inline int security_inode_setxattr(struct dentry 
*dentry,
return cap_inode_setxattr(dentry, name, value, size, flags);
 }
 
+static inline int security_inode_pre_setxattr(struct dentry *dentry,
+   const char *name, const void **value,
+   size_t *size, int flags, bool *alloc)
+{
+   return 0;
+}
+
 static inline void security_inode_post_setxattr(struct dentry *dentry,
const char *name, const void *value, size_t size, int flags)
 { }
diff --git a/security/security.c b/security/security.c
index abfc207..75d46b6 100644
--- a/security/security.c
+++ 

[PATCH v4 07/11] smack: abstraction layer for 2 common Smack operations

2015-10-14 Thread Lukasz Pawelczyk
This patch adds two new functions that provide an abstraction layer for
two common internal Smack operations:

smk_find_label_name() - returns a label name (char*) from a struct
smack_known pointer
smk_get_label()   - either finds or imports a label from a raw label
name (char*) and returns struct smack_known
pointer

This patch also simplifies some pieces of code due to addition of those
2 functions (e.g. smack_inode_post_setxattr, smk_fill_rule,
smk_write_revoke_subj).

It is meant as a preparation for namespaces patches. Those 2 functions
will serve as entry points for namespace operations.

This patch should not change the Smack behaviour in any way.

Signed-off-by: Lukasz Pawelczyk <l.pawelc...@samsung.com>
Reviewed-by: Casey Schaufler <ca...@schaufler-ca.com>
---
 security/smack/smack.h|   2 +
 security/smack/smack_access.c |  41 
 security/smack/smack_lsm.c|  78 +++---
 security/smack/smackfs.c  | 147 +++---
 4 files changed, 166 insertions(+), 102 deletions(-)

diff --git a/security/smack/smack.h b/security/smack/smack.h
index ca8fb7c..091efc2 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -306,6 +306,8 @@ int smack_has_ns_privilege(struct task_struct *task,
 int smack_has_privilege(struct task_struct *task, int cap);
 int smack_ns_privileged(struct user_namespace *user_ns, int cap);
 int smack_privileged(int cap);
+char *smk_find_label_name(struct smack_known *skp);
+struct smack_known *smk_get_label(const char *string, int len, bool import);
 
 /*
  * Shared data.
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 72f848e..131c742 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -716,3 +716,44 @@ int smack_privileged(int cap)
 {
return smack_ns_privileged(_user_ns, cap);
 }
+
+/**
+ * smk_find_label_name - A helper to get a string value of a label
+ * @skp: a label we want a string value from
+ *
+ * Returns a pointer to a label name or NULL if label name not found.
+ */
+char *smk_find_label_name(struct smack_known *skp)
+{
+   return skp->smk_known;
+}
+
+/**
+ * smk_get_label - A helper to get the smack_known value from a string using
+ * either import or find functions if it already exists
+ * @string: a name of a label we look for or want to import
+ * @len: the string size, or zero if it is NULL terminated
+ * @import: whether we should import the label if not found
+ *
+ * Returns a smack_known label that is either imported or found.
+ * NULL if label not found (only when import == false).
+ * Error code otherwise.
+ */
+struct smack_known *smk_get_label(const char *string, int len, bool import)
+{
+   struct smack_known *skp;
+   char *cp;
+
+   if (import) {
+   skp = smk_import_entry(string, len);
+   } else {
+   cp = smk_parse_smack(string, len);
+   if (IS_ERR(cp))
+   return ERR_CAST(cp);
+
+   skp = smk_find_entry(cp);
+   kfree(cp);
+   }
+
+   return skp;
+}
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 198d3d6..7303c37 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -746,31 +746,31 @@ static int smack_set_mnt_opts(struct super_block *sb,
for (i = 0; i < num_opts; i++) {
switch (opts->mnt_opts_flags[i]) {
case FSDEFAULT_MNT:
-   skp = smk_import_entry(opts->mnt_opts[i], 0);
+   skp = smk_get_label(opts->mnt_opts[i], 0, true);
if (IS_ERR(skp))
return PTR_ERR(skp);
sp->smk_default = skp;
break;
case FSFLOOR_MNT:
-   skp = smk_import_entry(opts->mnt_opts[i], 0);
+   skp = smk_get_label(opts->mnt_opts[i], 0, true);
if (IS_ERR(skp))
return PTR_ERR(skp);
sp->smk_floor = skp;
break;
case FSHAT_MNT:
-   skp = smk_import_entry(opts->mnt_opts[i], 0);
+   skp = smk_get_label(opts->mnt_opts[i], 0, true);
if (IS_ERR(skp))
return PTR_ERR(skp);
sp->smk_hat = skp;
break;
case FSROOT_MNT:
-   skp = smk_import_entry(opts->mnt_opts[i], 0);
+   skp = smk_get_label(opts->mnt_opts[i], 0, true);
if (IS_ERR(skp))
return PTR_ERR(skp);
sp->smk_root = skp;
break;

[PATCH v4 00/11] Smack namespace

2015-10-14 Thread Lukasz Pawelczyk
Fourth version of Smack namespace. Rebased for smack-for-4.4 with some
minor cosmetic changes.

Readme from v3 as there were the most significant changes:

https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg899383.html
https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg898638.html

1. the label map should be in /proc/.../attr/label_map and be handled
   generically.
2. The proper file system label (unmapped) should be written only once
   to remove a state where an incorrect label is on the filesystem.

Ad 1: Contrary to what Stephen said this unfortunately required LSM
modifications.

For reading: the map can be long, in principle longer than PAGE_SIZE to
which normal getprocattr hook is limited. So I invented a way for
getprocattr to be handled by seq operations. I think it is generic and
can be reused nicely by other LSMs. Also it doesn't break current LSM
code in any way. This created a new patch.

For writing: the default setprocattr arguments were not enough for me
to securely decide if the write access should be granted. To be in
parallel with user namespace I also needed credentials of the process
that actually opened the map (in addition to current). So I added a new
argument. This is also a new patch.

Ad 2: I really tried to make it work without introducing a new LSM
hook but changing a little semantics behind the current ones. Finally
I just added a simple inode_pre_setxattr hook that can swap the label
before it is written to the filesystem.  Hopefully this is ok. I
couldn't do this in inode_setxattr hook as Stephen suggested as this
hook is called before __vfs_setxattr_noperm which is an exported
symbol and is used sometimes without setxattr hence the logic had to
be inside that one. This is also a new patch.

I also added a new patch that "fixes" smackfs/syslog. I've noticed that
inside a namespace when I cat the file it shows "*". Even when I
remapped the star. After looking at the code it had it implicitly
displayed when it's not set. There were few problems with it:

1. In a namespace we can see a label that is not mapped.
2. There was no way to actually reset the value to default (NULL)
3. It was inconsistent from user space point of view:

# cat /smack/syslog
*

After the reboot the syslog hook doesn't limit anything, the
smack_syslog_label is NULL, but it displays star.

# echo '*' > /smack/syslog
# cat /smack/syslog
*

>From user space POV this is the same, file has star inside, but now for
the hook to pass the current needs to be star as well. And there is no
way to reset it back to NULL. So I treated syslog file the same way
unconfined and onlycap are handled. If it's empty, there is no label
set, hook doesn't limit anything (except for the cap). When it's filled
current needs to be equal for the hook to pass (as was before). But now
it can be reset back to NULL by writing EINVAL value (e.g. -syslog).
The syslog hook itself was not modified, only the file handling.

Changes from v3:
- rebased to the latest smack branch (smack-for-4.4)
- cosmetics in second patch reported by Paul Moore
- Acks from Paul Moore and Serge E. Hallyn on selected patches

Changes from v2:
- fix for config ifdefs in user_ns LSM hooks patch (CONFIG_USER_NS
  should've been used instead of CONFIG_SECURITY in several places)
- new patch for "smack_map" -> "attr/label_map" and new related
  getprocattr_seq lsm hook. With this change the code in further
  patches for handling smack_map has been moved to this new method
- new patch for setprocattr hook new argument, file's opener creds
- new patch for inode_pre_setxattr LSM hook
- new patch related to handling smackfs/syslog

Changes from v1:
- "kernel/exit.c: make sure current's nsproxy != NULL while checking
  caps" patch has been dropped
- fixed the title of the user_ns operations patch

Lukasz Pawelczyk (11):
  user_ns: 3 new LSM hooks for user namespace operations
  lsm: /proc/$PID/attr/label_map file and getprocattr_seq hook
  lsm: add file opener's cred to a setprocattr arguments
  lsm: inode_pre_setxattr hook
  smack: extend capability functions and fix 2 checks
  smack: don't use implicit star to display smackfs/syslog
  smack: abstraction layer for 2 common Smack operations
  smack: misc cleanups in preparation for a namespace patch
  smack: namespace groundwork
  smack: namespace implementation
  smack: documentation for the Smack namespace

 Documentation/security/00-INDEX|   2 +
 Documentation/security/Smack-namespace.txt | 231 +++
 MAINTAINERS|   1 +
 fs/proc/base.c |  83 +++-
 fs/xattr.c |  10 +
 include/linux/lsm_hooks.h  |  70 +++-
 include/linux/security.h   |  49 ++-
 include/linux/user_namespace.h |   4 +
 kernel/user.c  |   3 +
 kernel/user_namespace.c|  18 +
 se

[PATCH v4 09/11] smack: namespace groundwork

2015-10-14 Thread Lukasz Pawelczyk
This commit introduces several changes to Smack to prepare it for
namespace implementation. All the changes are related to namespaces.

Overview of the changes:
- Adds required data structures for mapped labels and functions to
  operate on them.
- Implements the proc interface /proc/$PID/attr/label_map that can be
  used for remapping of labels for a specific namespace. Also for
  checking the map.
- Modifies handling of special built-in labels. Detects them on import
  and assigns the same char* pointer regardless whether it's used in a
  normal or a mapped label. This way we can always compare them by ==
  instead of strcmp().
- Adds User namespace hooks implementation

This patch introduces both internal and user-space visible APIs to
handle namespaced labels and Smack namespaces but the behaviour of Smack
should not be changed. The APIs are there, but they have no impact yet.

Signed-off-by: Lukasz Pawelczyk <l.pawelc...@samsung.com>
Reviewed-by: Casey Schaufler <ca...@schaufler-ca.com>
---
 security/smack/Kconfig|  10 ++
 security/smack/Makefile   |   1 +
 security/smack/smack.h|  45 -
 security/smack/smack_access.c |  47 -
 security/smack/smack_lsm.c| 134 +-
 security/smack/smack_ns.c | 404 ++
 6 files changed, 626 insertions(+), 15 deletions(-)
 create mode 100644 security/smack/smack_ns.c

diff --git a/security/smack/Kconfig b/security/smack/Kconfig
index 271adae..b19a7fb 100644
--- a/security/smack/Kconfig
+++ b/security/smack/Kconfig
@@ -40,3 +40,13 @@ config SECURITY_SMACK_NETFILTER
  This enables security marking of network packets using
  Smack labels.
  If you are unsure how to answer this question, answer N.
+
+config SECURITY_SMACK_NS
+   bool "Smack namespace"
+   depends on SECURITY_SMACK
+   depends on USER_NS
+   help
+ This enables Smack namespace that makes it possible to map
+ specific labels within user namespace (analogously to mapping
+ UIDs) and to gain MAC capabilities over them.
+ If you are unsure how to answer this question, answer N.
diff --git a/security/smack/Makefile b/security/smack/Makefile
index ee2ebd5..5faebd7 100644
--- a/security/smack/Makefile
+++ b/security/smack/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_SECURITY_SMACK) := smack.o
 
 smack-y := smack_lsm.o smack_access.o smackfs.o
 smack-$(CONFIG_SECURITY_SMACK_NETFILTER) += smack_netfilter.o
+smack-$(CONFIG_SECURITY_SMACK_NS) += smack_ns.o
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 98bb676..4b7489f 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Use IPv6 port labeling if IPv6 is enabled and secmarks
@@ -74,8 +75,36 @@ struct smack_known {
struct netlbl_lsm_secattr   smk_netlabel;   /* on wire labels */
struct list_headsmk_rules;  /* access rules */
struct mutexsmk_rules_lock; /* lock for rules */
+#ifdef CONFIG_SECURITY_SMACK_NS
+   struct list_headsmk_mapped; /* namespaced labels */
+   struct mutexsmk_mapped_lock;
+#endif /* CONFIG_SECURITY_SMACK_NS */
 };
 
+#ifdef CONFIG_SECURITY_SMACK_NS
+
+/*
+ * User namespace security pointer content.
+ */
+struct smack_ns {
+   struct list_headsmk_mapped; /* namespaced labels */
+   struct mutexsmk_mapped_lock;
+};
+
+/*
+ * A single entry for a namespaced/mapped label.
+ */
+struct smack_known_ns {
+   struct list_headsmk_list_known;
+   struct list_headsmk_list_ns;
+   struct user_namespace   *smk_ns;
+   char*smk_mapped;
+   struct smack_known  *smk_unmapped;
+   boolsmk_allocated;
+};
+
+#endif /* CONFIG_SECURITY_SMACK_NS */
+
 /*
  * Maximum number of bytes for the levels in a CIPSO IP option.
  * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
@@ -295,7 +324,7 @@ int smk_tskacc(struct task_struct *, struct smack_known *,
   u32, struct smk_audit_info *);
 int smk_curacc(struct smack_known *, u32, struct smk_audit_info *);
 struct smack_known *smack_from_secid(const u32);
-char *smk_parse_smack(const char *string, int len);
+char *smk_parse_smack(const char *string, int len, bool *allocated);
 int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
 struct smack_known *smk_import_entry(const char *, int);
 void smk_insert_entry(struct smack_known *skp);
@@ -310,6 +339,20 @@ char *smk_find_label_name(struct smack_known *skp);
 struct smack_known *smk_get_label(const char *string, int len, bool import);
 
 /*
+ * These functions are in smack_ns.c
+ */
+#ifdef CONFIG_SECURITY_SMACK_NS
+struct user_namespace *smk_find_mapped_ns(struct user_namespace *ns);
+struct smack_known_ns *smk_find_mapped(s