summaryrefslogtreecommitdiff
path: root/security/smack
diff options
context:
space:
mode:
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack.h37
-rw-r--r--security/smack/smack_access.c104
-rw-r--r--security/smack/smack_lsm.c370
-rw-r--r--security/smack/smack_netfilter.c4
-rw-r--r--security/smack/smackfs.c132
5 files changed, 409 insertions, 238 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 4608b07607a3..9b9eb262fe33 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -42,7 +42,7 @@
/*
* This is the repository for labels seen so that it is
- * not necessary to keep allocating tiny chuncks of memory
+ * not necessary to keep allocating tiny chunks of memory
* and so that they can be shared.
*
* Labels are never modified in place. Anytime a label
@@ -152,6 +152,7 @@ struct smk_net4addr {
struct smack_known *smk_label; /* label */
};
+#if IS_ENABLED(CONFIG_IPV6)
/*
* An entry in the table identifying IPv6 hosts.
*/
@@ -162,7 +163,9 @@ struct smk_net6addr {
int smk_masks; /* mask size */
struct smack_known *smk_label; /* label */
};
+#endif /* CONFIG_IPV6 */
+#ifdef SMACK_IPV6_PORT_LABELING
/*
* An entry in the table identifying ports.
*/
@@ -175,6 +178,7 @@ struct smk_port_label {
short smk_sock_type; /* Socket type */
short smk_can_reuse;
};
+#endif /* SMACK_IPV6_PORT_LABELING */
struct smack_known_list_elem {
struct list_head list;
@@ -272,6 +276,20 @@ struct smk_audit_info {
};
/*
+ * Initialization
+ */
+#if defined(CONFIG_SECURITY_SMACK_NETFILTER)
+int smack_nf_ip_init(void);
+#else
+static inline int smack_nf_ip_init(void)
+{
+ return 0;
+}
+#endif
+int init_smk_fs(void);
+int smack_initcall(void);
+
+/*
* These functions are in smack_access.c
*/
int smk_access_entry(char *, char *, struct list_head *);
@@ -282,9 +300,12 @@ int smk_tskacc(struct task_smack *, struct smack_known *,
int smk_curacc(struct smack_known *, u32, struct smk_audit_info *);
int smack_str_from_perm(char *string, int access);
struct smack_known *smack_from_secid(const u32);
+int smk_parse_label_len(const char *string, int len);
char *smk_parse_smack(const char *string, int len);
int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
struct smack_known *smk_import_entry(const char *, int);
+struct smack_known *smk_import_valid_label(const char *label, int label_len,
+ gfp_t gfp);
void smk_insert_entry(struct smack_known *skp);
struct smack_known *smk_find_entry(const char *);
bool smack_privileged(int cap);
@@ -315,7 +336,9 @@ extern struct smack_known smack_known_web;
extern struct mutex smack_known_lock;
extern struct list_head smack_known_list;
extern struct list_head smk_net4addr_list;
+#if IS_ENABLED(CONFIG_IPV6)
extern struct list_head smk_net6addr_list;
+#endif /* CONFIG_IPV6 */
extern struct mutex smack_onlycap_lock;
extern struct list_head smack_onlycap_list;
@@ -426,6 +449,12 @@ static inline struct smack_known *smk_of_current(void)
return smk_of_task(smack_cred(current_cred()));
}
+void smack_log(char *subject_label, char *object_label,
+ int request,
+ int result, struct smk_audit_info *auditdata);
+
+#ifdef CONFIG_AUDIT
+
/*
* logging functions
*/
@@ -433,12 +462,6 @@ static inline struct smack_known *smk_of_current(void)
#define SMACK_AUDIT_ACCEPT 0x2
extern int log_policy;
-void smack_log(char *subject_label, char *object_label,
- int request,
- int result, struct smk_audit_info *auditdata);
-
-#ifdef CONFIG_AUDIT
-
/*
* some inline functions to set up audit data
* they do nothing if CONFIG_AUDIT is not set
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 3727379623e2..350b88d582b3 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -45,11 +45,13 @@ LIST_HEAD(smack_known_list);
*/
static u32 smack_next_secid = 10;
+#ifdef CONFIG_AUDIT
/*
* what events do we log
* can be overwritten at run-time by /smack/logging
*/
int log_policy = SMACK_AUDIT_DENIED;
+#endif /* CONFIG_AUDIT */
/**
* smk_access_entry - look up matching access rule
@@ -242,7 +244,7 @@ int smk_tskacc(struct task_smack *tsp, struct smack_known *obj_known,
}
/*
- * Allow for priviliged to override policy.
+ * Allow for privileged to override policy.
*/
if (rc != 0 && smack_privileged(CAP_MAC_OVERRIDE))
rc = 0;
@@ -276,7 +278,7 @@ int smk_curacc(struct smack_known *obj_known,
}
/**
- * smack_str_from_perm : helper to transalate an int to a
+ * smack_str_from_perm : helper to translate an int to a
* readable string
* @string : the string to fill
* @access : the int
@@ -390,7 +392,7 @@ void smack_log(char *subject_label, char *object_label, int request,
}
#else /* #ifdef CONFIG_AUDIT */
void smack_log(char *subject_label, char *object_label, int request,
- int result, struct smk_audit_info *ad)
+ int result, struct smk_audit_info *ad)
{
}
#endif
@@ -441,19 +443,19 @@ struct smack_known *smk_find_entry(const char *string)
}
/**
- * smk_parse_smack - parse smack label from a text string
- * @string: a text string that might contain a Smack label
- * @len: the maximum size, or zero if it is NULL terminated.
+ * smk_parse_label_len - calculate the length of the starting segment
+ * in the string that constitutes a valid smack label
+ * @string: a text string that might contain a Smack label at the beginning
+ * @len: the maximum size to look into, may be zero if string is null-terminated
*
- * Returns a pointer to the clean label or an error code.
+ * Returns the length of the segment (0 < L < SMK_LONGLABEL) or an error code.
*/
-char *smk_parse_smack(const char *string, int len)
+int smk_parse_label_len(const char *string, int len)
{
- char *smack;
int i;
- if (len <= 0)
- len = strlen(string) + 1;
+ if (len <= 0 || len > SMK_LONGLABEL)
+ len = SMK_LONGLABEL;
/*
* Reserve a leading '-' as an indicator that
@@ -461,7 +463,7 @@ char *smk_parse_smack(const char *string, int len)
* including /smack/cipso and /smack/cipso2
*/
if (string[0] == '-')
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
for (i = 0; i < len; i++)
if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' ||
@@ -469,6 +471,25 @@ char *smk_parse_smack(const char *string, int len)
break;
if (i == 0 || i >= SMK_LONGLABEL)
+ return -EINVAL;
+
+ return i;
+}
+
+/**
+ * smk_parse_smack - copy the starting segment in the string
+ * that constitutes a valid smack label
+ * @string: a text string that might contain a Smack label at the beginning
+ * @len: the maximum size to look into, may be zero if string is null-terminated
+ *
+ * Returns a pointer to the copy of the label or an error code.
+ */
+char *smk_parse_smack(const char *string, int len)
+{
+ char *smack;
+ int i = smk_parse_label_len(string, len);
+
+ if (i < 0)
return ERR_PTR(-EINVAL);
smack = kstrndup(string, i, GFP_NOFS);
@@ -552,31 +573,26 @@ int smack_populate_secattr(struct smack_known *skp)
}
/**
- * smk_import_entry - import a label, return the list entry
- * @string: a text string that might be a Smack label
- * @len: the maximum size, or zero if it is NULL terminated.
+ * smk_import_valid_allocated_label - import a label, return the list entry
+ * @smack: a text string that is a valid Smack label and may be kfree()ed.
+ * It is consumed: either becomes a part of the entry or kfree'ed.
+ * @gfp: Allocation type
*
- * Returns a pointer to the entry in the label list that
- * matches the passed string, adding it if necessary,
- * or an error code.
+ * Returns: see description of smk_import_entry()
*/
-struct smack_known *smk_import_entry(const char *string, int len)
+static struct smack_known *
+smk_import_allocated_label(char *smack, gfp_t gfp)
{
struct smack_known *skp;
- char *smack;
int rc;
- smack = smk_parse_smack(string, len);
- if (IS_ERR(smack))
- return ERR_CAST(smack);
-
mutex_lock(&smack_known_lock);
skp = smk_find_entry(smack);
if (skp != NULL)
goto freeout;
- skp = kzalloc(sizeof(*skp), GFP_NOFS);
+ skp = kzalloc_obj(*skp, gfp);
if (skp == NULL) {
skp = ERR_PTR(-ENOMEM);
goto freeout;
@@ -607,6 +623,44 @@ unlockout:
}
/**
+ * smk_import_entry - import a label, return the list entry
+ * @string: a text string that might contain a Smack label at the beginning
+ * @len: the maximum size to look into, may be zero if string is null-terminated
+ *
+ * Returns a pointer to the entry in the label list that
+ * matches the passed string, adding it if necessary,
+ * or an error code.
+ */
+struct smack_known *smk_import_entry(const char *string, int len)
+{
+ char *smack = smk_parse_smack(string, len);
+
+ if (IS_ERR(smack))
+ return ERR_CAST(smack);
+
+ return smk_import_allocated_label(smack, GFP_NOFS);
+}
+
+/**
+ * smk_import_valid_label - import a label, return the list entry
+ * @label: a text string that is a valid Smack label, not null-terminated
+ * @label_len: the length of the text string in the @label
+ * @gfp: the GFP mask used for allocating memory for the @label text string copy
+ *
+ * Return: see description of smk_import_entry()
+ */
+struct smack_known *
+smk_import_valid_label(const char *label, int label_len, gfp_t gfp)
+{
+ char *smack = kstrndup(label, label_len, gfp);
+
+ if (!smack)
+ return ERR_PTR(-ENOMEM);
+
+ return smk_import_allocated_label(smack, gfp);
+}
+
+/**
* smack_from_secid - find the Smack label associated with a secid
* @secid: an integer that might be associated with a Smack label
*
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 239773cdcdcf..3f9ae05039a2 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -24,7 +24,6 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
-#include <linux/dccp.h>
#include <linux/icmpv6.h>
#include <linux/slab.h>
#include <linux/mutex.h>
@@ -183,7 +182,7 @@ static int smk_bu_inode(struct inode *inode, int mode, int rc)
char acc[SMK_NUM_ACCESS_TYPE + 1];
if (isp->smk_flags & SMK_INODE_IMPURE)
- pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
+ pr_info("Smack Unconfined Corruption: inode=(%s %llu) %s\n",
inode->i_sb->s_id, inode->i_ino, current->comm);
if (rc <= 0)
@@ -196,7 +195,7 @@ static int smk_bu_inode(struct inode *inode, int mode, int rc)
smk_bu_mode(mode, acc);
- pr_info("Smack %s: (%s %s %s) inode=(%s %ld) %s\n", smk_bu_mess[rc],
+ pr_info("Smack %s: (%s %s %s) inode=(%s %llu) %s\n", smk_bu_mess[rc],
tsp->smk_task->smk_known, isp->smk_inode->smk_known, acc,
inode->i_sb->s_id, inode->i_ino, current->comm);
return 0;
@@ -215,7 +214,7 @@ static int smk_bu_file(struct file *file, int mode, int rc)
char acc[SMK_NUM_ACCESS_TYPE + 1];
if (isp->smk_flags & SMK_INODE_IMPURE)
- pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
+ pr_info("Smack Unconfined Corruption: inode=(%s %llu) %s\n",
inode->i_sb->s_id, inode->i_ino, current->comm);
if (rc <= 0)
@@ -224,7 +223,7 @@ static int smk_bu_file(struct file *file, int mode, int rc)
rc = 0;
smk_bu_mode(mode, acc);
- pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
+ pr_info("Smack %s: (%s %s %s) file=(%s %llu %pD) %s\n", smk_bu_mess[rc],
sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
inode->i_sb->s_id, inode->i_ino, file,
current->comm);
@@ -245,7 +244,7 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
char acc[SMK_NUM_ACCESS_TYPE + 1];
if (isp->smk_flags & SMK_INODE_IMPURE)
- pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
+ pr_info("Smack Unconfined Corruption: inode=(%s %llu) %s\n",
inode->i_sb->s_id, inode->i_ino, current->comm);
if (rc <= 0)
@@ -254,7 +253,7 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
rc = 0;
smk_bu_mode(mode, acc);
- pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
+ pr_info("Smack %s: (%s %s %s) file=(%s %llu %pD) %s\n", smk_bu_mess[rc],
sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
inode->i_sb->s_id, inode->i_ino, file,
current->comm);
@@ -373,7 +372,7 @@ static int smk_copy_relabel(struct list_head *nhead, struct list_head *ohead,
struct smack_known_list_elem *oklep;
list_for_each_entry(oklep, ohead, list) {
- nklep = kzalloc(sizeof(struct smack_known_list_elem), gfp);
+ nklep = kzalloc_obj(struct smack_known_list_elem, gfp);
if (nklep == NULL) {
smk_destroy_label_list(nhead);
return -ENOMEM;
@@ -563,7 +562,7 @@ static int smack_add_opt(int token, const char *s, void **mnt_opts)
struct smack_known *skp;
if (!opts) {
- opts = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL);
+ opts = kzalloc_obj(struct smack_mnt_opts);
if (!opts)
return -ENOMEM;
*mnt_opts = opts;
@@ -623,7 +622,7 @@ static int smack_fs_context_submount(struct fs_context *fc,
struct smack_mnt_opts *ctx;
struct inode_smack *isp;
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ ctx = kzalloc_obj(*ctx);
if (!ctx)
return -ENOMEM;
fc->security = ctx;
@@ -674,7 +673,7 @@ static int smack_fs_context_dup(struct fs_context *fc,
if (!src)
return 0;
- fc->security = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL);
+ fc->security = kzalloc_obj(struct smack_mnt_opts);
if (!fc->security)
return -ENOMEM;
@@ -964,6 +963,42 @@ static int smack_inode_alloc_security(struct inode *inode)
}
/**
+ * smk_rule_transmutes - does access rule for (subject,object) contain 't'?
+ * @subject: a pointer to the subject's Smack label entry
+ * @object: a pointer to the object's Smack label entry
+ */
+static bool
+smk_rule_transmutes(struct smack_known *subject,
+ const struct smack_known *object)
+{
+ int may;
+
+ rcu_read_lock();
+ may = smk_access_entry(subject->smk_known, object->smk_known,
+ &subject->smk_rules);
+ rcu_read_unlock();
+ return (may > 0) && (may & MAY_TRANSMUTE);
+}
+
+static int
+xattr_dupval(struct xattr *xattrs, int *xattr_count,
+ const char *name, const void *value, unsigned int vallen)
+{
+ struct xattr * const xattr = lsm_get_xattr_slot(xattrs, xattr_count);
+
+ if (!xattr)
+ return 0;
+
+ xattr->value = kmemdup(value, vallen, GFP_NOFS);
+ if (!xattr->value)
+ return -ENOMEM;
+
+ xattr->value_len = vallen;
+ xattr->name = name;
+ return 0;
+}
+
+/**
* smack_inode_init_security - copy out the smack from an inode
* @inode: the newly created inode
* @dir: containing directory object
@@ -978,23 +1013,30 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
struct xattr *xattrs, int *xattr_count)
{
struct task_smack *tsp = smack_cred(current_cred());
- struct inode_smack *issp = smack_inode(inode);
- struct smack_known *skp = smk_of_task(tsp);
- struct smack_known *isp = smk_of_inode(inode);
+ struct inode_smack * const issp = smack_inode(inode);
struct smack_known *dsp = smk_of_inode(dir);
- struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
- int may;
+ int rc = 0;
+ int transflag = 0;
+ bool trans_cred;
+ bool trans_rule;
/*
+ * UNIX domain sockets use lower level socket data. Let
+ * UDS inode have fixed * label to keep smack_inode_permission() calm
+ * when called from unix_find_bsd()
+ */
+ if (S_ISSOCK(inode->i_mode)) {
+ /* forced label, no need to save to xattrs */
+ issp->smk_inode = &smack_known_star;
+ goto instant_inode;
+ }
+ /*
* If equal, transmuting already occurred in
* smack_dentry_create_files_as(). No need to check again.
*/
- if (tsp->smk_task != tsp->smk_transmuted) {
- rcu_read_lock();
- may = smk_access_entry(skp->smk_known, dsp->smk_known,
- &skp->smk_rules);
- rcu_read_unlock();
- }
+ trans_cred = (tsp->smk_task == tsp->smk_transmuted);
+ if (!trans_cred)
+ trans_rule = smk_rule_transmutes(smk_of_task(tsp), dsp);
/*
* In addition to having smk_task equal to smk_transmuted,
@@ -1002,47 +1044,38 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
* requests transmutation then by all means transmute.
* Mark the inode as changed.
*/
- if ((tsp->smk_task == tsp->smk_transmuted) ||
- (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
- smk_inode_transmutable(dir))) {
- struct xattr *xattr_transmute;
-
+ if (trans_cred || (trans_rule && smk_inode_transmutable(dir))) {
/*
* The caller of smack_dentry_create_files_as()
* should have overridden the current cred, so the
* inode label was already set correctly in
* smack_inode_alloc_security().
*/
- if (tsp->smk_task != tsp->smk_transmuted)
- isp = issp->smk_inode = dsp;
-
- issp->smk_flags |= SMK_INODE_TRANSMUTE;
- xattr_transmute = lsm_get_xattr_slot(xattrs,
- xattr_count);
- if (xattr_transmute) {
- xattr_transmute->value = kmemdup(TRANS_TRUE,
- TRANS_TRUE_SIZE,
- GFP_NOFS);
- if (!xattr_transmute->value)
- return -ENOMEM;
+ if (!trans_cred)
+ issp->smk_inode = dsp;
- xattr_transmute->value_len = TRANS_TRUE_SIZE;
- xattr_transmute->name = XATTR_SMACK_TRANSMUTE;
+ if (S_ISDIR(inode->i_mode)) {
+ transflag = SMK_INODE_TRANSMUTE;
+
+ if (xattr_dupval(xattrs, xattr_count,
+ XATTR_SMACK_TRANSMUTE,
+ TRANS_TRUE,
+ TRANS_TRUE_SIZE
+ ))
+ rc = -ENOMEM;
}
}
- issp->smk_flags |= SMK_INODE_INSTANT;
-
- if (xattr) {
- xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
- if (!xattr->value)
- return -ENOMEM;
-
- xattr->value_len = strlen(isp->smk_known);
- xattr->name = XATTR_SMACK_SUFFIX;
- }
-
- return 0;
+ if (rc == 0)
+ if (xattr_dupval(xattrs, xattr_count,
+ XATTR_SMACK_SUFFIX,
+ issp->smk_inode->smk_known,
+ strlen(issp->smk_inode->smk_known)
+ ))
+ rc = -ENOMEM;
+instant_inode:
+ issp->smk_flags |= (SMK_INODE_INSTANT | transflag);
+ return rc;
}
/**
@@ -1316,13 +1349,23 @@ static int smack_inode_setxattr(struct mnt_idmap *idmap,
int check_import = 0;
int check_star = 0;
int rc = 0;
+ umode_t const i_mode = d_backing_inode(dentry)->i_mode;
/*
* Check label validity here so import won't fail in post_setxattr
*/
- if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
- strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
- strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) {
+ if (strcmp(name, XATTR_NAME_SMACK) == 0) {
+ /*
+ * UDS inode has fixed label
+ */
+ if (S_ISSOCK(i_mode)) {
+ rc = -EINVAL;
+ } else {
+ check_priv = 1;
+ check_import = 1;
+ }
+ } else if (strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
+ strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) {
check_priv = 1;
check_import = 1;
} else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
@@ -1332,7 +1375,7 @@ static int smack_inode_setxattr(struct mnt_idmap *idmap,
check_star = 1;
} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
check_priv = 1;
- if (!S_ISDIR(d_backing_inode(dentry)->i_mode) ||
+ if (!S_ISDIR(i_mode) ||
size != TRANS_TRUE_SIZE ||
strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
rc = -EINVAL;
@@ -1463,12 +1506,15 @@ static int smack_inode_removexattr(struct mnt_idmap *idmap,
* Don't do anything special for these.
* XATTR_NAME_SMACKIPIN
* XATTR_NAME_SMACKIPOUT
+ * XATTR_NAME_SMACK if S_ISSOCK (UDS inode has fixed label)
*/
if (strcmp(name, XATTR_NAME_SMACK) == 0) {
- struct super_block *sbp = dentry->d_sb;
- struct superblock_smack *sbsp = smack_superblock(sbp);
+ if (!S_ISSOCK(d_backing_inode(dentry)->i_mode)) {
+ struct super_block *sbp = dentry->d_sb;
+ struct superblock_smack *sbsp = smack_superblock(sbp);
- isp->smk_inode = sbsp->smk_default;
+ isp->smk_inode = sbsp->smk_default;
+ }
} else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0)
isp->smk_task = NULL;
else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0)
@@ -1934,7 +1980,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
*/
file = fown->file;
- /* we don't log here as rc can be overriden */
+ /* we don't log here as rc can be overridden */
blob = smack_file(file);
skp = *blob;
rc = smk_access(skp, tkp, MAY_DELIVER, NULL);
@@ -2492,6 +2538,7 @@ static struct smack_known *smack_ipv4host_label(struct sockaddr_in *sip)
return NULL;
}
+#if IS_ENABLED(CONFIG_IPV6)
/*
* smk_ipv6_localhost - Check for local ipv6 host address
* @sip: the address
@@ -2559,6 +2606,7 @@ static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip)
return NULL;
}
+#endif /* CONFIG_IPV6 */
/**
* smack_netlbl_add - Set the secattr on a socket
@@ -2663,6 +2711,7 @@ static int smk_ipv4_check(struct sock *sk, struct sockaddr_in *sap)
return rc;
}
+#if IS_ENABLED(CONFIG_IPV6)
/**
* smk_ipv6_check - check Smack access
* @subject: subject Smack label
@@ -2695,6 +2744,7 @@ static int smk_ipv6_check(struct smack_known *subject,
rc = smk_bu_note("IPv6 check", subject, object, MAY_WRITE, rc);
return rc;
}
+#endif /* CONFIG_IPV6 */
#ifdef SMACK_IPV6_PORT_LABELING
/**
@@ -2767,7 +2817,7 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
/*
* A new port entry is required.
*/
- spp = kzalloc(sizeof(*spp), GFP_KERNEL);
+ spp = kzalloc_obj(*spp);
if (spp == NULL)
return;
@@ -3027,7 +3077,9 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
return 0;
if (addrlen < offsetofend(struct sockaddr, sa_family))
return 0;
- if (IS_ENABLED(CONFIG_IPV6) && sap->sa_family == AF_INET6) {
+
+#if IS_ENABLED(CONFIG_IPV6)
+ if (sap->sa_family == AF_INET6) {
struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap;
struct smack_known *rsp = NULL;
@@ -3047,6 +3099,8 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
return rc;
}
+#endif /* CONFIG_IPV6 */
+
if (sap->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in))
return 0;
rc = smk_ipv4_check(sock->sk, (struct sockaddr_in *)sap);
@@ -3578,7 +3632,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
*/
/*
- * UNIX domain sockets use lower level socket data.
+ * UDS inode has fixed label (*)
*/
if (S_ISSOCK(inode->i_mode)) {
final = &smack_known_star;
@@ -3656,7 +3710,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
* @attr: which attribute to fetch
* @ctx: buffer to receive the result
* @size: available size in, actual size out
- * @flags: unused
+ * @flags: reserved, currently zero
*
* Fill the passed user space @ctx with the details of the requested
* attribute.
@@ -3717,47 +3771,55 @@ static int smack_getprocattr(struct task_struct *p, const char *name, char **val
* Sets the Smack value of the task. Only setting self
* is permitted and only with privilege
*
- * Returns the length of the smack label or an error code
+ * Returns zero on success or an error code
*/
-static int do_setattr(u64 attr, void *value, size_t size)
+static int do_setattr(unsigned int attr, void *value, size_t size)
{
struct task_smack *tsp = smack_cred(current_cred());
struct cred *new;
struct smack_known *skp;
- struct smack_known_list_elem *sklep;
- int rc;
-
- if (!smack_privileged(CAP_MAC_ADMIN) && list_empty(&tsp->smk_relabel))
- return -EPERM;
+ int label_len;
+ /*
+ * let unprivileged user validate input, check permissions later
+ */
if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
return -EINVAL;
- if (attr != LSM_ATTR_CURRENT)
- return -EOPNOTSUPP;
-
- skp = smk_import_entry(value, size);
- if (IS_ERR(skp))
- return PTR_ERR(skp);
+ label_len = smk_parse_label_len(value, size);
+ if (label_len < 0 || label_len != size)
+ return -EINVAL;
/*
* No process is ever allowed the web ("@") label
* and the star ("*") label.
*/
- if (skp == &smack_known_web || skp == &smack_known_star)
- return -EINVAL;
+ if (label_len == 1 /* '@', '*' */) {
+ const char c = *(const char *)value;
+
+ if (c == *smack_known_web.smk_known ||
+ c == *smack_known_star.smk_known)
+ return -EPERM;
+ }
if (!smack_privileged(CAP_MAC_ADMIN)) {
- rc = -EPERM;
- list_for_each_entry(sklep, &tsp->smk_relabel, list)
- if (sklep->smk_label == skp) {
- rc = 0;
- break;
- }
- if (rc)
- return rc;
+ const struct smack_known_list_elem *sklep;
+ list_for_each_entry(sklep, &tsp->smk_relabel, list) {
+ const char *cp = sklep->smk_label->smk_known;
+
+ if (strlen(cp) == label_len &&
+ strncmp(cp, value, label_len) == 0)
+ goto in_relabel;
+ }
+ return -EPERM;
+in_relabel:
+ ;
}
+ skp = smk_import_valid_label(value, label_len, GFP_KERNEL);
+ if (IS_ERR(skp))
+ return PTR_ERR(skp);
+
new = prepare_creds();
if (new == NULL)
return -ENOMEM;
@@ -3770,7 +3832,7 @@ static int do_setattr(u64 attr, void *value, size_t size)
smk_destroy_label_list(&tsp->smk_relabel);
commit_creds(new);
- return size;
+ return 0;
}
/**
@@ -3778,7 +3840,7 @@ static int do_setattr(u64 attr, void *value, size_t size)
* @attr: which attribute to set
* @ctx: buffer containing the data
* @size: size of @ctx
- * @flags: unused
+ * @flags: reserved, must be zero
*
* Fill the passed user space @ctx with the details of the requested
* attribute.
@@ -3788,12 +3850,26 @@ static int do_setattr(u64 attr, void *value, size_t size)
static int smack_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
u32 size, u32 flags)
{
- int rc;
+ if (attr != LSM_ATTR_CURRENT)
+ return -EOPNOTSUPP;
- rc = do_setattr(attr, ctx->ctx, ctx->ctx_len);
- if (rc > 0)
- return 0;
- return rc;
+ if (ctx->flags)
+ return -EINVAL;
+ /*
+ * string must have \0 terminator, included in ctx->ctx
+ * (see description of struct lsm_ctx)
+ */
+ if (ctx->ctx_len == 0)
+ return -EINVAL;
+
+ if (ctx->ctx[ctx->ctx_len - 1] != '\0')
+ return -EINVAL;
+ /*
+ * other do_setattr() caller, smack_setprocattr(),
+ * does not count \0 into size, so
+ * decreasing length by 1 to accommodate the divergence.
+ */
+ return do_setattr(attr, ctx->ctx, ctx->ctx_len - 1);
}
/**
@@ -3805,15 +3881,39 @@ static int smack_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
* Sets the Smack value of the task. Only setting self
* is permitted and only with privilege
*
- * Returns the length of the smack label or an error code
+ * Returns the size of the input value or an error code
*/
static int smack_setprocattr(const char *name, void *value, size_t size)
{
- int attr = lsm_name_to_attr(name);
+ size_t realsize = size;
+ unsigned int attr = lsm_name_to_attr(name);
- if (attr != LSM_ATTR_UNDEF)
- return do_setattr(attr, value, size);
- return -EINVAL;
+ switch (attr) {
+ case LSM_ATTR_UNDEF: return -EINVAL;
+ default: return -EOPNOTSUPP;
+ case LSM_ATTR_CURRENT:
+ ;
+ }
+
+ /*
+ * The value for the "current" attribute is the label
+ * followed by one of the 4 trailers: none, \0, \n, \n\0
+ *
+ * I.e. following inputs are accepted as 3-characters long label "foo":
+ *
+ * "foo" (3 characters)
+ * "foo\0" (4 characters)
+ * "foo\n" (4 characters)
+ * "foo\n\0" (5 characters)
+ */
+
+ if (realsize && (((const char *)value)[realsize - 1] == '\0'))
+ --realsize;
+
+ if (realsize && (((const char *)value)[realsize - 1] == '\n'))
+ --realsize;
+
+ return do_setattr(attr, value, realsize) ? : size;
}
/**
@@ -4053,7 +4153,6 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
__be16 frag_off;
struct tcphdr _tcph, *th;
struct udphdr _udph, *uh;
- struct dccp_hdr _dccph, *dh;
sip->sin6_port = 0;
@@ -4077,16 +4176,10 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
sip->sin6_port = th->source;
break;
case IPPROTO_UDP:
- case IPPROTO_UDPLITE:
uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
if (uh != NULL)
sip->sin6_port = uh->source;
break;
- case IPPROTO_DCCP:
- dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
- if (dh != NULL)
- sip->sin6_port = dh->dccph_sport;
- break;
}
return proto;
}
@@ -4195,7 +4288,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
/*
* Receiving a packet requires that the other end
* be able to write here. Read access is not required.
- * This is the simplist possible security model
+ * This is the simplest possible security model
* for networking.
*/
rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad);
@@ -4207,8 +4300,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
#if IS_ENABLED(CONFIG_IPV6)
case PF_INET6:
proto = smk_skb_to_addr_ipv6(skb, &sadd);
- if (proto != IPPROTO_UDP && proto != IPPROTO_UDPLITE &&
- proto != IPPROTO_TCP && proto != IPPROTO_DCCP)
+ if (proto != IPPROTO_UDP && proto != IPPROTO_TCP)
break;
#ifdef SMACK_IPV6_SECMARK_LABELING
skp = smack_from_skb(skb);
@@ -4343,29 +4435,6 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
}
/**
- * smack_sock_graft - Initialize a newly created socket with an existing sock
- * @sk: child sock
- * @parent: parent socket
- *
- * Set the smk_{in,out} state of an existing sock based on the process that
- * is creating the new socket.
- */
-static void smack_sock_graft(struct sock *sk, struct socket *parent)
-{
- struct socket_smack *ssp;
- struct smack_known *skp = smk_of_current();
-
- if (sk == NULL ||
- (sk->sk_family != PF_INET && sk->sk_family != PF_INET6))
- return;
-
- ssp = smack_sock(sk);
- ssp->smk_in = skp;
- ssp->smk_out = skp;
- /* cssp->smk_packet is already set in smack_inet_csk_clone() */
-}
-
-/**
* smack_inet_conn_request - Smack access check on connect
* @sk: socket involved
* @skb: packet
@@ -4701,7 +4770,7 @@ static int smack_post_notification(const struct cred *w_cred,
* @gfp: type of the memory for the allocation
*
* Prepare to audit cases where (@field @op @rulestr) is true.
- * The label to be audited is created if necessay.
+ * The label to be audited is created if necessary.
*/
static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule,
gfp_t gfp)
@@ -4872,6 +4941,11 @@ static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
static int smack_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
{
+ /*
+ * UDS inode has fixed label. Ignore nfs label.
+ */
+ if (S_ISSOCK(inode->i_mode))
+ return 0;
return smack_inode_setsecurity(inode, XATTR_SMACK_SUFFIX, ctx,
ctxlen, 0);
}
@@ -4930,14 +5004,13 @@ static int smack_inode_copy_up_xattr(struct dentry *src, const char *name)
}
static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
- struct qstr *name,
+ const struct qstr *name,
const struct cred *old,
struct cred *new)
{
struct task_smack *otsp = smack_cred(old);
struct task_smack *ntsp = smack_cred(new);
struct inode_smack *isp;
- int may;
/*
* Use the process credential unless all of
@@ -4951,18 +5024,12 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
isp = smack_inode(d_inode(dentry->d_parent));
if (isp->smk_flags & SMK_INODE_TRANSMUTE) {
- rcu_read_lock();
- may = smk_access_entry(otsp->smk_task->smk_known,
- isp->smk_inode->smk_known,
- &otsp->smk_task->smk_rules);
- rcu_read_unlock();
-
/*
* If the directory is transmuting and the rule
* providing access is transmuting use the containing
* directory label instead of the process label.
*/
- if (may > 0 && (may & MAY_TRANSMUTE)) {
+ if (smk_rule_transmutes(otsp->smk_task, isp->smk_inode)) {
ntsp->smk_task = isp->smk_inode;
ntsp->smk_transmuted = ntsp->smk_task;
}
@@ -5179,7 +5246,6 @@ static struct security_hook_list smack_hooks[] __ro_after_init = {
LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
#endif
LSM_HOOK_INIT(sk_clone_security, smack_sk_clone_security),
- LSM_HOOK_INIT(sock_graft, smack_sock_graft),
LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone),
@@ -5290,16 +5356,30 @@ static __init int smack_init(void)
/* initialize the smack_known_list */
init_smack_known_list();
+ /* Inform the audit system that secctx is used */
+ audit_cfg_lsm(&smack_lsmid,
+ AUDIT_CFG_LSM_SECCTX_SUBJECT |
+ AUDIT_CFG_LSM_SECCTX_OBJECT);
+
return 0;
}
+int __init smack_initcall(void)
+{
+ int rc_fs = init_smk_fs();
+ int rc_nf = smack_nf_ip_init();
+
+ return rc_fs ? rc_fs : rc_nf;
+}
+
/*
* Smack requires early initialization in order to label
* all processes and objects when they are created.
*/
DEFINE_LSM(smack) = {
- .name = "smack",
+ .id = &smack_lsmid,
.flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
.blobs = &smack_blob_sizes,
.init = smack_init,
+ .initcall_device = smack_initcall,
};
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
index 8fd747b3653a..17ba578b1308 100644
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c
@@ -68,7 +68,7 @@ static struct pernet_operations smack_net_ops = {
.exit = smack_nf_unregister,
};
-static int __init smack_nf_ip_init(void)
+int __init smack_nf_ip_init(void)
{
if (smack_enabled == 0)
return 0;
@@ -76,5 +76,3 @@ static int __init smack_nf_ip_init(void)
printk(KERN_DEBUG "Smack: Registering netfilter hooks\n");
return register_pernet_subsys(&smack_net_ops);
}
-
-__initcall(smack_nf_ip_init);
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 357188f764ce..6e62dcb36f74 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -41,7 +41,9 @@ enum smk_inos {
SMK_AMBIENT = 7, /* internet ambient label */
SMK_NET4ADDR = 8, /* single label hosts */
SMK_ONLYCAP = 9, /* the only "capable" label */
+#ifdef CONFIG_AUDIT
SMK_LOGGING = 10, /* logging */
+#endif /* CONFIG_AUDIT */
SMK_LOAD_SELF = 11, /* task specific rules */
SMK_ACCESSES = 12, /* access policy */
SMK_MAPPED = 13, /* CIPSO level indicating mapped label */
@@ -68,6 +70,7 @@ enum smk_inos {
static DEFINE_MUTEX(smack_cipso_lock);
static DEFINE_MUTEX(smack_ambient_lock);
static DEFINE_MUTEX(smk_net4addr_lock);
+static DEFINE_MUTEX(smk_cipso_doi_lock);
#if IS_ENABLED(CONFIG_IPV6)
static DEFINE_MUTEX(smk_net6addr_lock);
#endif /* CONFIG_IPV6 */
@@ -139,7 +142,7 @@ struct smack_parsed_rule {
int smk_access2;
};
-static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
+static u32 smk_cipso_doi_value = CIPSO_V4_DOI_UNKNOWN;
/*
* Values for parsing cipso rules
@@ -165,7 +168,7 @@ static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
/*
- * Stricly for CIPSO level manipulation.
+ * Strictly for CIPSO level manipulation.
* Set the category bit number in a smack label sized buffer.
*/
static inline void smack_catset_bit(unsigned int cat, char *catsetp)
@@ -661,43 +664,60 @@ static const struct file_operations smk_load_ops = {
};
/**
- * smk_cipso_doi - initialize the CIPSO domain
+ * smk_cipso_doi - set netlabel maps
+ * @ndoi: new value for our CIPSO DOI
+ * @gfp_flags: kmalloc allocation context
*/
-static void smk_cipso_doi(void)
+static int
+smk_cipso_doi(u32 ndoi, gfp_t gfp_flags)
{
- int rc;
+ int rc = 0;
struct cipso_v4_doi *doip;
struct netlbl_audit nai;
- smk_netlabel_audit_set(&nai);
+ mutex_lock(&smk_cipso_doi_lock);
- rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
- if (rc != 0)
- printk(KERN_WARNING "%s:%d remove rc = %d\n",
- __func__, __LINE__, rc);
+ if (smk_cipso_doi_value == ndoi)
+ goto clr_doi_lock;
- doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL | __GFP_NOFAIL);
+ smk_netlabel_audit_set(&nai);
+
+ doip = kmalloc_obj(struct cipso_v4_doi, gfp_flags);
+ if (!doip) {
+ rc = -ENOMEM;
+ goto clr_doi_lock;
+ }
doip->map.std = NULL;
- doip->doi = smk_cipso_doi_value;
+ doip->doi = ndoi;
doip->type = CIPSO_V4_MAP_PASS;
doip->tags[0] = CIPSO_V4_TAG_RBITMAP;
for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)
doip->tags[rc] = CIPSO_V4_TAG_INVALID;
rc = netlbl_cfg_cipsov4_add(doip, &nai);
- if (rc != 0) {
- printk(KERN_WARNING "%s:%d cipso add rc = %d\n",
- __func__, __LINE__, rc);
+ if (rc) {
kfree(doip);
- return;
+ goto clr_doi_lock;
}
- rc = netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai);
- if (rc != 0) {
- printk(KERN_WARNING "%s:%d map add rc = %d\n",
- __func__, __LINE__, rc);
- netlbl_cfg_cipsov4_del(doip->doi, &nai);
- return;
+
+ if (smk_cipso_doi_value != CIPSO_V4_DOI_UNKNOWN) {
+ rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
+ if (rc && rc != -ENOENT)
+ goto clr_ndoi_def;
+
+ netlbl_cfg_cipsov4_del(smk_cipso_doi_value, &nai);
}
+
+ rc = netlbl_cfg_cipsov4_map_add(ndoi, NULL, NULL, NULL, &nai);
+ if (rc) {
+ smk_cipso_doi_value = CIPSO_V4_DOI_UNKNOWN; // no default map
+clr_ndoi_def: netlbl_cfg_cipsov4_del(ndoi, &nai);
+ } else
+ smk_cipso_doi_value = ndoi;
+
+clr_doi_lock:
+ mutex_unlock(&smk_cipso_doi_lock);
+ return rc;
}
/**
@@ -812,7 +832,7 @@ static int smk_open_cipso(struct inode *inode, struct file *file)
static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
size_t count, loff_t *ppos, int format)
{
- struct netlbl_lsm_catmap *old_cat, *new_cat = NULL;
+ struct netlbl_lsm_catmap *old_cat;
struct smack_known *skp;
struct netlbl_lsm_secattr ncats;
char mapcatset[SMK_CIPSOLEN];
@@ -899,22 +919,15 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
smack_catset_bit(cat, mapcatset);
}
- ncats.flags = 0;
- if (catlen == 0) {
- ncats.attr.mls.cat = NULL;
- ncats.attr.mls.lvl = maplevel;
- new_cat = netlbl_catmap_alloc(GFP_ATOMIC);
- if (new_cat)
- new_cat->next = ncats.attr.mls.cat;
- ncats.attr.mls.cat = new_cat;
- skp->smk_netlabel.flags &= ~(1U << 3);
- rc = 0;
- } else {
- rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
- }
+
+ rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
if (rc >= 0) {
old_cat = skp->smk_netlabel.attr.mls.cat;
rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat);
+ if (ncats.attr.mls.cat)
+ skp->smk_netlabel.flags |= NETLBL_SECATTR_MLS_CAT;
+ else
+ skp->smk_netlabel.flags &= ~(u32)NETLBL_SECATTR_MLS_CAT;
skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl;
synchronize_rcu();
netlbl_catmap_free(old_cat);
@@ -1082,13 +1095,12 @@ static int smk_open_net4addr(struct inode *inode, struct file *file)
}
/**
- * smk_net4addr_insert
+ * smk_net4addr_insert - insert a new entry into the net4addrs list
* @new : netlabel to insert
*
- * This helper insert netlabel in the smack_net4addrs list
+ * This helper inserts netlabel in the smack_net4addrs list
* sorted by netmask length (longest to smallest)
- * locked by &smk_net4addr_lock in smk_write_net4addr
- *
+ * locked by &smk_net4addr_lock in smk_write_net4addr.
*/
static void smk_net4addr_insert(struct smk_net4addr *new)
{
@@ -1237,7 +1249,7 @@ static ssize_t smk_write_net4addr(struct file *file, const char __user *buf,
smk_netlabel_audit_set(&audit_info);
if (found == 0) {
- snp = kzalloc(sizeof(*snp), GFP_KERNEL);
+ snp = kzalloc_obj(*snp);
if (snp == NULL)
rc = -ENOMEM;
else {
@@ -1345,13 +1357,12 @@ static int smk_open_net6addr(struct inode *inode, struct file *file)
}
/**
- * smk_net6addr_insert
+ * smk_net6addr_insert - insert a new entry into the net6addrs list
* @new : entry to insert
*
* This inserts an entry in the smack_net6addrs list
* sorted by netmask length (longest to smallest)
- * locked by &smk_net6addr_lock in smk_write_net6addr
- *
+ * locked by &smk_net6addr_lock in smk_write_net6addr.
*/
static void smk_net6addr_insert(struct smk_net6addr *new)
{
@@ -1515,7 +1526,7 @@ static ssize_t smk_write_net6addr(struct file *file, const char __user *buf,
break;
}
if (found == 0) {
- snp = kzalloc(sizeof(*snp), GFP_KERNEL);
+ snp = kzalloc_obj(*snp);
if (snp == NULL)
rc = -ENOMEM;
else {
@@ -1569,7 +1580,7 @@ static ssize_t smk_read_doi(struct file *filp, char __user *buf,
if (*ppos != 0)
return 0;
- sprintf(temp, "%d", smk_cipso_doi_value);
+ sprintf(temp, "%lu", (unsigned long)smk_cipso_doi_value);
rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
return rc;
@@ -1588,7 +1599,7 @@ static ssize_t smk_write_doi(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
char temp[80];
- int i;
+ unsigned long u;
if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
@@ -1601,14 +1612,13 @@ static ssize_t smk_write_doi(struct file *file, const char __user *buf,
temp[count] = '\0';
- if (sscanf(temp, "%d", &i) != 1)
+ if (kstrtoul(temp, 10, &u))
return -EINVAL;
- smk_cipso_doi_value = i;
-
- smk_cipso_doi();
+ if (u == CIPSO_V4_DOI_UNKNOWN || u > U32_MAX)
+ return -EINVAL;
- return count;
+ return smk_cipso_doi(u, GFP_KERNEL) ? : count;
}
static const struct file_operations smk_doi_ops = {
@@ -1960,7 +1970,7 @@ static int smk_parse_label_list(char *data, struct list_head *list)
if (IS_ERR(skp))
return PTR_ERR(skp);
- sklep = kzalloc(sizeof(*sklep), GFP_KERNEL);
+ sklep = kzalloc_obj(*sklep);
if (sklep == NULL)
return -ENOMEM;
@@ -2133,6 +2143,7 @@ static const struct file_operations smk_unconfined_ops = {
};
#endif /* CONFIG_SECURITY_SMACK_BRINGUP */
+#ifdef CONFIG_AUDIT
/**
* smk_read_logging - read() for /smack/logging
* @filp: file pointer, not actually used
@@ -2197,6 +2208,7 @@ static const struct file_operations smk_logging_ops = {
.write = smk_write_logging,
.llseek = default_llseek,
};
+#endif /* CONFIG_AUDIT */
/*
* Seq_file read operations for /smack/load-self
@@ -2883,8 +2895,10 @@ static int smk_fill_super(struct super_block *sb, struct fs_context *fc)
"netlabel", &smk_net4addr_ops, S_IRUGO|S_IWUSR},
[SMK_ONLYCAP] = {
"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
+#ifdef CONFIG_AUDIT
[SMK_LOGGING] = {
"logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
+#endif /* CONFIG_AUDIT */
[SMK_LOAD_SELF] = {
"load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
[SMK_ACCESSES] = {
@@ -2963,7 +2977,7 @@ static int smk_init_fs_context(struct fs_context *fc)
static struct file_system_type smk_fs_type = {
.name = "smackfs",
.init_fs_context = smk_init_fs_context,
- .kill_sb = kill_litter_super,
+ .kill_sb = kill_anon_super,
};
static struct vfsmount *smackfs_mount;
@@ -2981,10 +2995,11 @@ static struct vfsmount *smackfs_mount;
* Returns true if we were not chosen on boot or if
* we were chosen and filesystem registration succeeded.
*/
-static int __init init_smk_fs(void)
+int __init init_smk_fs(void)
{
int err;
int rc;
+ struct netlbl_audit nai;
if (smack_enabled == 0)
return 0;
@@ -3003,7 +3018,10 @@ static int __init init_smk_fs(void)
}
}
- smk_cipso_doi();
+ smk_netlabel_audit_set(&nai);
+ (void) netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
+ (void) smk_cipso_doi(SMACK_CIPSO_DOI_DEFAULT,
+ GFP_KERNEL | __GFP_NOFAIL);
smk_unlbl_ambient(NULL);
rc = smack_populate_secattr(&smack_known_floor);
@@ -3024,5 +3042,3 @@ static int __init init_smk_fs(void)
return err;
}
-
-__initcall(init_smk_fs);