Loading Documentation/security/Smack.txt +164 −40 Original line number Original line Diff line number Diff line Loading @@ -15,7 +15,7 @@ at hand. Smack consists of three major components: Smack consists of three major components: - The kernel - The kernel - A start-up script and a few modified applications - Basic utilities, which are helpful but not required - Configuration data - Configuration data The kernel component of Smack is implemented as a Linux The kernel component of Smack is implemented as a Linux Loading @@ -23,37 +23,28 @@ Security Modules (LSM) module. It requires netlabel and works best with file systems that support extended attributes, works best with file systems that support extended attributes, although xattr support is not strictly required. although xattr support is not strictly required. It is safe to run a Smack kernel under a "vanilla" distribution. It is safe to run a Smack kernel under a "vanilla" distribution. Smack kernels use the CIPSO IP option. Some network Smack kernels use the CIPSO IP option. Some network configurations are intolerant of IP options and can impede configurations are intolerant of IP options and can impede access to systems that use them as Smack does. access to systems that use them as Smack does. The startup script etc-init.d-smack should be installed The current git repositories for Smack user space are: in /etc/init.d/smack and should be invoked early in the start-up process. On Fedora rc5.d/S02smack is recommended. This script ensures that certain devices have the correct Smack attributes and loads the Smack configuration if any is defined. This script invokes two programs that ensure configuration data is properly formatted. These programs are /usr/sbin/smackload and /usr/sin/smackcipso. The system will run just fine without these programs, but it will be difficult to set access rules properly. A version of "ls" that provides a "-M" option to display Smack labels on long listing is available. A hacked version of sshd that allows network logins by users git@gitorious.org:meego-platform-security/smackutil.git with specific Smack labels is available. This version does git@gitorious.org:meego-platform-security/libsmack.git not work for scp. You must set the /etc/ssh/sshd_config line: UsePrivilegeSeparation no The format of /etc/smack/usr is: These should make and install on most modern distributions. There are three commands included in smackutil: username smack smackload - properly formats data for writing to /smack/load smackcipso - properly formats data for writing to /smack/cipso chsmack - display or set Smack extended attribute values In keeping with the intent of Smack, configuration data is In keeping with the intent of Smack, configuration data is minimal and not strictly required. The most important minimal and not strictly required. The most important configuration step is mounting the smackfs pseudo filesystem. configuration step is mounting the smackfs pseudo filesystem. If smackutil is installed the startup script will take care of this, but it can be manually as well. Add this line to /etc/fstab: Add this line to /etc/fstab: Loading @@ -61,19 +52,148 @@ Add this line to /etc/fstab: and create the /smack directory for mounting. and create the /smack directory for mounting. Smack uses extended attributes (xattrs) to store file labels. Smack uses extended attributes (xattrs) to store labels on filesystem The command to set a Smack label on a file is: objects. The attributes are stored in the extended attribute security name space. A process must have CAP_MAC_ADMIN to change any of these attributes. The extended attributes that Smack uses are: SMACK64 Used to make access control decisions. In almost all cases the label given to a new filesystem object will be the label of the process that created it. SMACK64EXEC The Smack label of a process that execs a program file with this attribute set will run with this attribute's value. SMACK64MMAP Don't allow the file to be mmapped by a process whose Smack label does not allow all of the access permitted to a process with the label contained in this attribute. This is a very specific use case for shared libraries. SMACK64TRANSMUTE Can only have the value "TRUE". If this attribute is present on a directory when an object is created in the directory and the Smack rule (more below) that permitted the write access to the directory includes the transmute ("t") mode the object gets the label of the directory instead of the label of the creating process. If the object being created is a directory the SMACK64TRANSMUTE attribute is set as well. SMACK64IPIN This attribute is only available on file descriptors for sockets. Use the Smack label in this attribute for access control decisions on packets being delivered to this socket. SMACK64IPOUT This attribute is only available on file descriptors for sockets. Use the Smack label in this attribute for access control decisions on packets coming from this socket. There are multiple ways to set a Smack label on a file: # attr -S -s SMACK64 -V "value" path # attr -S -s SMACK64 -V "value" path # chsmack -a value path NOTE: Smack labels are limited to 23 characters. The attr command A process can see the smack label it is running with by does not enforce this restriction and can be used to set reading /proc/self/attr/current. A process with CAP_MAC_ADMIN invalid Smack labels on files. can set the process smack by writing there. If you don't do anything special all users will get the floor ("_") Most Smack configuration is accomplished by writing to files label when they log in. If you do want to log in via the hacked ssh in the smackfs filesystem. This pseudo-filesystem is usually at other labels use the attr command to set the smack value on the mounted on /smack. home directory and its contents. access This interface reports whether a subject with the specified Smack label has a particular access to an object with a specified Smack label. Write a fixed format access rule to this file. The next read will indicate whether the access would be permitted. The text will be either "1" indicating access, or "0" indicating denial. access2 This interface reports whether a subject with the specified Smack label has a particular access to an object with a specified Smack label. Write a long format access rule to this file. The next read will indicate whether the access would be permitted. The text will be either "1" indicating access, or "0" indicating denial. ambient This contains the Smack label applied to unlabeled network packets. cipso This interface allows a specific CIPSO header to be assigned to a Smack label. The format accepted on write is: "%24s%4d%4d"["%4d"]... The first string is a fixed Smack label. The first number is the level to use. The second number is the number of categories. The following numbers are the categories. "level-3-cats-5-19 3 2 5 19" cipso2 This interface allows a specific CIPSO header to be assigned to a Smack label. The format accepted on write is: "%s%4d%4d"["%4d"]... The first string is a long Smack label. The first number is the level to use. The second number is the number of categories. The following numbers are the categories. "level-3-cats-5-19 3 2 5 19" direct This contains the CIPSO level used for Smack direct label representation in network packets. doi This contains the CIPSO domain of interpretation used in network packets. load This interface allows access control rules in addition to the system defined rules to be specified. The format accepted on write is: "%24s%24s%5s" where the first string is the subject label, the second the object label, and the third the requested access. The access string may contain only the characters "rwxat-", and specifies which sort of access is allowed. The "-" is a placeholder for permissions that are not allowed. The string "r-x--" would specify read and execute access. Labels are limited to 23 characters in length. load2 This interface allows access control rules in addition to the system defined rules to be specified. The format accepted on write is: "%s %s %s" where the first string is the subject label, the second the object label, and the third the requested access. The access string may contain only the characters "rwxat-", and specifies which sort of access is allowed. The "-" is a placeholder for permissions that are not allowed. The string "r-x--" would specify read and execute access. load-self This interface allows process specific access rules to be defined. These rules are only consulted if access would otherwise be permitted, and are intended to provide additional restrictions on the process. The format is the same as for the load interface. load-self2 This interface allows process specific access rules to be defined. These rules are only consulted if access would otherwise be permitted, and are intended to provide additional restrictions on the process. The format is the same as for the load2 interface. logging This contains the Smack logging state. mapped This contains the CIPSO level used for Smack mapped label representation in network packets. netlabel This interface allows specific internet addresses to be treated as single label hosts. Packets are sent to single label hosts without CIPSO headers, but only from processes that have Smack write access to the host label. All packets received from single label hosts are given the specified label. The format accepted on write is: "%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label". onlycap This contains the label processes must have for CAP_MAC_ADMIN and CAP_MAC_OVERRIDE to be effective. If this file is empty these capabilities are effective at for processes with any label. The value is set by writing the desired label to the file or cleared by writing "-" to the file. You can add access rules in /etc/smack/accesses. They take the form: You can add access rules in /etc/smack/accesses. They take the form: Loading @@ -83,10 +203,6 @@ access is a combination of the letters rwxa which specify the kind of access permitted a subject with subjectlabel on an kind of access permitted a subject with subjectlabel on an object with objectlabel. If there is no rule no access is allowed. object with objectlabel. If there is no rule no access is allowed. A process can see the smack label it is running with by reading /proc/self/attr/current. A privileged process can set the process smack by writing there. Look for additional programs on http://schaufler-ca.com Look for additional programs on http://schaufler-ca.com From the Smack Whitepaper: From the Smack Whitepaper: Loading Loading @@ -186,7 +302,7 @@ team. Smack labels are unstructured, case sensitive, and the only operation ever performed on them is comparison for equality. Smack labels cannot ever performed on them is comparison for equality. Smack labels cannot contain unprintable characters, the "/" (slash), the "\" (backslash), the "'" contain unprintable characters, the "/" (slash), the "\" (backslash), the "'" (quote) and '"' (double-quote) characters. (quote) and '"' (double-quote) characters. Smack labels cannot begin with a '-', which is reserved for special options. Smack labels cannot begin with a '-'. This is reserved for special options. There are some predefined labels: There are some predefined labels: Loading @@ -194,7 +310,7 @@ There are some predefined labels: ^ Pronounced "hat", a single circumflex character. ^ Pronounced "hat", a single circumflex character. * Pronounced "star", a single asterisk character. * Pronounced "star", a single asterisk character. ? Pronounced "huh", a single question mark character. ? Pronounced "huh", a single question mark character. @ Pronounced "Internet", a single at sign character. @ Pronounced "web", a single at sign character. Every task on a Smack system is assigned a label. System tasks, such as Every task on a Smack system is assigned a label. System tasks, such as init(8) and systems daemons, are run with the floor ("_") label. User tasks init(8) and systems daemons, are run with the floor ("_") label. User tasks Loading Loading @@ -246,13 +362,14 @@ The format of an access rule is: Where subject-label is the Smack label of the task, object-label is the Smack Where subject-label is the Smack label of the task, object-label is the Smack label of the thing being accessed, and access is a string specifying the sort label of the thing being accessed, and access is a string specifying the sort of access allowed. The Smack labels are limited to 23 characters. The access of access allowed. The access specification is searched for letters that specification is searched for letters that describe access modes: describe access modes: a: indicates that append access should be granted. a: indicates that append access should be granted. r: indicates that read access should be granted. r: indicates that read access should be granted. w: indicates that write access should be granted. w: indicates that write access should be granted. x: indicates that execute access should be granted. x: indicates that execute access should be granted. t: indicates that the rule requests transmutation. Uppercase values for the specification letters are allowed as well. Uppercase values for the specification letters are allowed as well. Access mode specifications can be in any order. Examples of acceptable rules Access mode specifications can be in any order. Examples of acceptable rules Loading @@ -273,7 +390,7 @@ Examples of unacceptable rules are: Spaces are not allowed in labels. Since a subject always has access to files Spaces are not allowed in labels. Since a subject always has access to files with the same label specifying a rule for that case is pointless. Only with the same label specifying a rule for that case is pointless. Only valid letters (rwxaRWXA) and the dash ('-') character are allowed in valid letters (rwxatRWXAT) and the dash ('-') character are allowed in access specifications. The dash is a placeholder, so "a-r" is the same access specifications. The dash is a placeholder, so "a-r" is the same as "ar". A lone dash is used to specify that no access should be allowed. as "ar". A lone dash is used to specify that no access should be allowed. Loading @@ -297,6 +414,13 @@ but not any of its attributes by the circumstance of having read access to the containing directory but not to the differently labeled file. This is an containing directory but not to the differently labeled file. This is an artifact of the file name being data in the directory, not a part of the file. artifact of the file name being data in the directory, not a part of the file. If a directory is marked as transmuting (SMACK64TRANSMUTE=TRUE) and the access rule that allows a process to create an object in that directory includes 't' access the label assigned to the new object will be that of the directory, not the creating process. This makes it much easier for two processes with different labels to share data without granting access to all of their files. IPC objects, message queues, semaphore sets, and memory segments exist in flat IPC objects, message queues, semaphore sets, and memory segments exist in flat namespaces and access requests are only required to match the object in namespaces and access requests are only required to match the object in question. question. Loading security/smack/smack.h +21 −36 Original line number Original line Diff line number Diff line Loading @@ -23,13 +23,19 @@ #include <linux/lsm_audit.h> #include <linux/lsm_audit.h> /* /* * Smack labels were limited to 23 characters for a long time. */ #define SMK_LABELLEN 24 #define SMK_LONGLABEL 256 /* * 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 * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is * bigger than can be used, and 24 is the next lower multiple * bigger than can be used, and 24 is the next lower multiple * of 8, and there are too many issues if there isn't space set * of 8, and there are too many issues if there isn't space set * aside for the terminating null byte. * aside for the terminating null byte. */ */ #define SMK_MAXLEN 23 #define SMK_CIPSOLEN 24 #define SMK_LABELLEN (SMK_MAXLEN+1) struct superblock_smack { struct superblock_smack { char *smk_root; char *smk_root; Loading Loading @@ -66,6 +72,7 @@ struct task_smack { #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ #define SMK_INODE_CHANGED 0x04 /* smack was transmuted */ /* /* * A label access rule. * A label access rule. Loading @@ -77,15 +84,6 @@ struct smack_rule { int smk_access; int smk_access; }; }; /* * An entry in the table mapping smack values to * CIPSO level/category-set values. */ struct smack_cipso { int smk_level; char smk_catset[SMK_LABELLEN]; }; /* /* * An entry in the table identifying hosts. * An entry in the table identifying hosts. */ */ Loading Loading @@ -113,9 +111,7 @@ struct smk_netlbladdr { * interfaces don't. The secid should go away when all of * interfaces don't. The secid should go away when all of * these components have been repaired. * these components have been repaired. * * * If there is a cipso value associated with the label it * The cipso value associated with the label gets stored here, too. * gets stored here, too. This will most likely be rare as * the cipso direct mapping in used internally. * * * Keep the access rules for this subject label here so that * Keep the access rules for this subject label here so that * the entire set of rules does not need to be examined every * the entire set of rules does not need to be examined every Loading @@ -123,12 +119,11 @@ struct smk_netlbladdr { */ */ struct smack_known { struct smack_known { struct list_head list; struct list_head list; char smk_known[SMK_LABELLEN]; char *smk_known; u32 smk_secid; u32 smk_secid; struct smack_cipso *smk_cipso; struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */ spinlock_t smk_cipsolock; /* for changing cipso map */ struct list_head smk_rules; /* access rules */ struct list_head smk_rules; /* access rules */ struct mutex smk_rules_lock; /* lock for the rules */ struct mutex smk_rules_lock; /* lock for rules */ }; }; /* /* Loading Loading @@ -165,6 +160,7 @@ struct smack_known { #define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ #define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ #define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */ #define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */ #define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */ #define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */ #define SMACK_CIPSO_MAPPED_DEFAULT 251 /* Also arbitrary */ #define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */ #define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */ #define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */ #define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */ #define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ #define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ Loading Loading @@ -215,10 +211,9 @@ struct inode_smack *new_inode_smack(char *); int smk_access_entry(char *, char *, struct list_head *); int smk_access_entry(char *, char *, struct list_head *); int smk_access(char *, char *, int, struct smk_audit_info *); int smk_access(char *, char *, int, struct smk_audit_info *); int smk_curacc(char *, u32, struct smk_audit_info *); int smk_curacc(char *, u32, struct smk_audit_info *); int smack_to_cipso(const char *, struct smack_cipso *); char *smack_from_cipso(u32, char *); char *smack_from_secid(const u32); char *smack_from_secid(const u32); void smk_parse_smack(const char *string, int len, char *smack); char *smk_parse_smack(const char *string, int len); int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); char *smk_import(const char *, int); char *smk_import(const char *, int); struct smack_known *smk_import_entry(const char *, int); struct smack_known *smk_import_entry(const char *, int); struct smack_known *smk_find_entry(const char *); struct smack_known *smk_find_entry(const char *); Loading @@ -228,6 +223,7 @@ u32 smack_to_secid(const char *); * Shared data. * Shared data. */ */ extern int smack_cipso_direct; extern int smack_cipso_direct; extern int smack_cipso_mapped; extern char *smack_net_ambient; extern char *smack_net_ambient; extern char *smack_onlycap; extern char *smack_onlycap; extern const char *smack_cipso_option; extern const char *smack_cipso_option; Loading @@ -239,23 +235,12 @@ extern struct smack_known smack_known_invalid; extern struct smack_known smack_known_star; extern struct smack_known smack_known_star; extern struct smack_known smack_known_web; extern struct smack_known smack_known_web; extern struct mutex smack_known_lock; extern struct list_head smack_known_list; extern struct list_head smack_known_list; extern struct list_head smk_netlbladdr_list; extern struct list_head smk_netlbladdr_list; extern struct security_operations smack_ops; extern struct security_operations smack_ops; /* * Stricly for CIPSO level manipulation. * Set the category bit number in a smack label sized buffer. */ static inline void smack_catset_bit(int cat, char *catsetp) { if (cat > SMK_LABELLEN * 8) return; catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8); } /* /* * Is the directory transmuting? * Is the directory transmuting? */ */ Loading security/smack/smack_access.c +116 −117 Original line number Original line Diff line number Diff line Loading @@ -19,37 +19,31 @@ struct smack_known smack_known_huh = { struct smack_known smack_known_huh = { .smk_known = "?", .smk_known = "?", .smk_secid = 2, .smk_secid = 2, .smk_cipso = NULL, }; }; struct smack_known smack_known_hat = { struct smack_known smack_known_hat = { .smk_known = "^", .smk_known = "^", .smk_secid = 3, .smk_secid = 3, .smk_cipso = NULL, }; }; struct smack_known smack_known_star = { struct smack_known smack_known_star = { .smk_known = "*", .smk_known = "*", .smk_secid = 4, .smk_secid = 4, .smk_cipso = NULL, }; }; struct smack_known smack_known_floor = { struct smack_known smack_known_floor = { .smk_known = "_", .smk_known = "_", .smk_secid = 5, .smk_secid = 5, .smk_cipso = NULL, }; }; struct smack_known smack_known_invalid = { struct smack_known smack_known_invalid = { .smk_known = "", .smk_known = "", .smk_secid = 6, .smk_secid = 6, .smk_cipso = NULL, }; }; struct smack_known smack_known_web = { struct smack_known smack_known_web = { .smk_known = "@", .smk_known = "@", .smk_secid = 7, .smk_secid = 7, .smk_cipso = NULL, }; }; LIST_HEAD(smack_known_list); LIST_HEAD(smack_known_list); Loading Loading @@ -331,7 +325,7 @@ void smack_log(char *subject_label, char *object_label, int request, } } #endif #endif static DEFINE_MUTEX(smack_known_lock); DEFINE_MUTEX(smack_known_lock); /** /** * smk_find_entry - find a label on the list, return the list entry * smk_find_entry - find a label on the list, return the list entry Loading @@ -345,7 +339,7 @@ struct smack_known *smk_find_entry(const char *string) struct smack_known *skp; struct smack_known *skp; list_for_each_entry_rcu(skp, &smack_known_list, list) { list_for_each_entry_rcu(skp, &smack_known_list, list) { if (strncmp(skp->smk_known, string, SMK_MAXLEN) == 0) if (strcmp(skp->smk_known, string) == 0) return skp; return skp; } } Loading @@ -356,27 +350,76 @@ struct smack_known *smk_find_entry(const char *string) * smk_parse_smack - parse smack label from a text string * smk_parse_smack - parse smack label from a text string * @string: a text string that might contain a Smack label * @string: a text string that might contain a Smack label * @len: the maximum size, or zero if it is NULL terminated. * @len: the maximum size, or zero if it is NULL terminated. * @smack: parsed smack label, or NULL if parse error * * Returns a pointer to the clean label, or NULL */ */ void smk_parse_smack(const char *string, int len, char *smack) char *smk_parse_smack(const char *string, int len) { { int found; char *smack; int i; int i; if (len <= 0 || len > SMK_MAXLEN) if (len <= 0) len = SMK_MAXLEN; len = strlen(string) + 1; for (i = 0, found = 0; i < SMK_LABELLEN; i++) { /* if (found) * Reserve a leading '-' as an indicator that smack[i] = '\0'; * this isn't a label, but an option to interfaces else if (i >= len || string[i] > '~' || string[i] <= ' ' || * including /smack/cipso and /smack/cipso2 string[i] == '/' || string[i] == '"' || */ string[i] == '\\' || string[i] == '\'') { if (string[0] == '-') return NULL; for (i = 0; i < len; i++) if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' || string[i] == '"' || string[i] == '\\' || string[i] == '\'') break; if (i == 0 || i >= SMK_LONGLABEL) return NULL; smack = kzalloc(i + 1, GFP_KERNEL); if (smack != NULL) { strncpy(smack, string, i + 1); smack[i] = '\0'; smack[i] = '\0'; found = 1; } else smack[i] = string[i]; } } return smack; } /** * smk_netlbl_mls - convert a catset to netlabel mls categories * @catset: the Smack categories * @sap: where to put the netlabel categories * * Allocates and fills attr.mls * Returns 0 on success, error code on failure. */ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap, int len) { unsigned char *cp; unsigned char m; int cat; int rc; int byte; sap->flags |= NETLBL_SECATTR_MLS_CAT; sap->attr.mls.lvl = level; sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); sap->attr.mls.cat->startbit = 0; for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++) for (m = 0x80; m != 0; m >>= 1, cat++) { if ((m & *cp) == 0) continue; rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat, cat, GFP_ATOMIC); if (rc < 0) { netlbl_secattr_catmap_free(sap->attr.mls.cat); return rc; } } return 0; } } /** /** Loading @@ -390,33 +433,59 @@ void smk_parse_smack(const char *string, int len, char *smack) struct smack_known *smk_import_entry(const char *string, int len) struct smack_known *smk_import_entry(const char *string, int len) { { struct smack_known *skp; struct smack_known *skp; char smack[SMK_LABELLEN]; char *smack; int slen; int rc; smk_parse_smack(string, len, smack); smack = smk_parse_smack(string, len); if (smack[0] == '\0') if (smack == NULL) return NULL; return NULL; mutex_lock(&smack_known_lock); mutex_lock(&smack_known_lock); skp = smk_find_entry(smack); skp = smk_find_entry(smack); if (skp != NULL) goto freeout; if (skp == NULL) { skp = kzalloc(sizeof(*skp), GFP_KERNEL); skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL); if (skp == NULL) if (skp != NULL) { goto freeout; strncpy(skp->smk_known, smack, SMK_MAXLEN); skp->smk_known = smack; skp->smk_secid = smack_next_secid++; skp->smk_secid = smack_next_secid++; skp->smk_cipso = NULL; skp->smk_netlabel.domain = skp->smk_known; skp->smk_netlabel.flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; /* * If direct labeling works use it. * Otherwise use mapped labeling. */ slen = strlen(smack); if (slen < SMK_CIPSOLEN) rc = smk_netlbl_mls(smack_cipso_direct, skp->smk_known, &skp->smk_netlabel, slen); else rc = smk_netlbl_mls(smack_cipso_mapped, (char *)&skp->smk_secid, &skp->smk_netlabel, sizeof(skp->smk_secid)); if (rc >= 0) { INIT_LIST_HEAD(&skp->smk_rules); INIT_LIST_HEAD(&skp->smk_rules); spin_lock_init(&skp->smk_cipsolock); mutex_init(&skp->smk_rules_lock); mutex_init(&skp->smk_rules_lock); /* /* * Make sure that the entry is actually * Make sure that the entry is actually * filled before putting it on the list. * filled before putting it on the list. */ */ list_add_rcu(&skp->list, &smack_known_list); list_add_rcu(&skp->list, &smack_known_list); goto unlockout; } } } /* * smk_netlbl_mls failed. */ kfree(skp); skp = NULL; freeout: kfree(smack); unlockout: mutex_unlock(&smack_known_lock); mutex_unlock(&smack_known_lock); return skp; return skp; Loading Loading @@ -479,79 +548,9 @@ char *smack_from_secid(const u32 secid) */ */ u32 smack_to_secid(const char *smack) u32 smack_to_secid(const char *smack) { { struct smack_known *skp; struct smack_known *skp = smk_find_entry(smack); rcu_read_lock(); list_for_each_entry_rcu(skp, &smack_known_list, list) { if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) { rcu_read_unlock(); return skp->smk_secid; } } rcu_read_unlock(); return 0; } /** * smack_from_cipso - find the Smack label associated with a CIPSO option * @level: Bell & LaPadula level from the network * @cp: Bell & LaPadula categories from the network * * This is a simple lookup in the label table. * * Return the matching label from the label list or NULL. */ char *smack_from_cipso(u32 level, char *cp) { struct smack_known *kp; char *final = NULL; rcu_read_lock(); list_for_each_entry(kp, &smack_known_list, list) { if (kp->smk_cipso == NULL) continue; spin_lock_bh(&kp->smk_cipsolock); if (kp->smk_cipso->smk_level == level && memcmp(kp->smk_cipso->smk_catset, cp, SMK_LABELLEN) == 0) final = kp->smk_known; spin_unlock_bh(&kp->smk_cipsolock); if (skp == NULL) if (final != NULL) break; } rcu_read_unlock(); return final; } /** * smack_to_cipso - find the CIPSO option to go with a Smack label * @smack: a pointer to the smack label in question * @cp: where to put the result * * Returns zero if a value is available, non-zero otherwise. */ int smack_to_cipso(const char *smack, struct smack_cipso *cp) { struct smack_known *kp; int found = 0; rcu_read_lock(); list_for_each_entry_rcu(kp, &smack_known_list, list) { if (kp->smk_known == smack || strcmp(kp->smk_known, smack) == 0) { found = 1; break; } } rcu_read_unlock(); if (found == 0 || kp->smk_cipso == NULL) return -ENOENT; memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso)); return 0; return 0; return skp->smk_secid; } } Loading
Documentation/security/Smack.txt +164 −40 Original line number Original line Diff line number Diff line Loading @@ -15,7 +15,7 @@ at hand. Smack consists of three major components: Smack consists of three major components: - The kernel - The kernel - A start-up script and a few modified applications - Basic utilities, which are helpful but not required - Configuration data - Configuration data The kernel component of Smack is implemented as a Linux The kernel component of Smack is implemented as a Linux Loading @@ -23,37 +23,28 @@ Security Modules (LSM) module. It requires netlabel and works best with file systems that support extended attributes, works best with file systems that support extended attributes, although xattr support is not strictly required. although xattr support is not strictly required. It is safe to run a Smack kernel under a "vanilla" distribution. It is safe to run a Smack kernel under a "vanilla" distribution. Smack kernels use the CIPSO IP option. Some network Smack kernels use the CIPSO IP option. Some network configurations are intolerant of IP options and can impede configurations are intolerant of IP options and can impede access to systems that use them as Smack does. access to systems that use them as Smack does. The startup script etc-init.d-smack should be installed The current git repositories for Smack user space are: in /etc/init.d/smack and should be invoked early in the start-up process. On Fedora rc5.d/S02smack is recommended. This script ensures that certain devices have the correct Smack attributes and loads the Smack configuration if any is defined. This script invokes two programs that ensure configuration data is properly formatted. These programs are /usr/sbin/smackload and /usr/sin/smackcipso. The system will run just fine without these programs, but it will be difficult to set access rules properly. A version of "ls" that provides a "-M" option to display Smack labels on long listing is available. A hacked version of sshd that allows network logins by users git@gitorious.org:meego-platform-security/smackutil.git with specific Smack labels is available. This version does git@gitorious.org:meego-platform-security/libsmack.git not work for scp. You must set the /etc/ssh/sshd_config line: UsePrivilegeSeparation no The format of /etc/smack/usr is: These should make and install on most modern distributions. There are three commands included in smackutil: username smack smackload - properly formats data for writing to /smack/load smackcipso - properly formats data for writing to /smack/cipso chsmack - display or set Smack extended attribute values In keeping with the intent of Smack, configuration data is In keeping with the intent of Smack, configuration data is minimal and not strictly required. The most important minimal and not strictly required. The most important configuration step is mounting the smackfs pseudo filesystem. configuration step is mounting the smackfs pseudo filesystem. If smackutil is installed the startup script will take care of this, but it can be manually as well. Add this line to /etc/fstab: Add this line to /etc/fstab: Loading @@ -61,19 +52,148 @@ Add this line to /etc/fstab: and create the /smack directory for mounting. and create the /smack directory for mounting. Smack uses extended attributes (xattrs) to store file labels. Smack uses extended attributes (xattrs) to store labels on filesystem The command to set a Smack label on a file is: objects. The attributes are stored in the extended attribute security name space. A process must have CAP_MAC_ADMIN to change any of these attributes. The extended attributes that Smack uses are: SMACK64 Used to make access control decisions. In almost all cases the label given to a new filesystem object will be the label of the process that created it. SMACK64EXEC The Smack label of a process that execs a program file with this attribute set will run with this attribute's value. SMACK64MMAP Don't allow the file to be mmapped by a process whose Smack label does not allow all of the access permitted to a process with the label contained in this attribute. This is a very specific use case for shared libraries. SMACK64TRANSMUTE Can only have the value "TRUE". If this attribute is present on a directory when an object is created in the directory and the Smack rule (more below) that permitted the write access to the directory includes the transmute ("t") mode the object gets the label of the directory instead of the label of the creating process. If the object being created is a directory the SMACK64TRANSMUTE attribute is set as well. SMACK64IPIN This attribute is only available on file descriptors for sockets. Use the Smack label in this attribute for access control decisions on packets being delivered to this socket. SMACK64IPOUT This attribute is only available on file descriptors for sockets. Use the Smack label in this attribute for access control decisions on packets coming from this socket. There are multiple ways to set a Smack label on a file: # attr -S -s SMACK64 -V "value" path # attr -S -s SMACK64 -V "value" path # chsmack -a value path NOTE: Smack labels are limited to 23 characters. The attr command A process can see the smack label it is running with by does not enforce this restriction and can be used to set reading /proc/self/attr/current. A process with CAP_MAC_ADMIN invalid Smack labels on files. can set the process smack by writing there. If you don't do anything special all users will get the floor ("_") Most Smack configuration is accomplished by writing to files label when they log in. If you do want to log in via the hacked ssh in the smackfs filesystem. This pseudo-filesystem is usually at other labels use the attr command to set the smack value on the mounted on /smack. home directory and its contents. access This interface reports whether a subject with the specified Smack label has a particular access to an object with a specified Smack label. Write a fixed format access rule to this file. The next read will indicate whether the access would be permitted. The text will be either "1" indicating access, or "0" indicating denial. access2 This interface reports whether a subject with the specified Smack label has a particular access to an object with a specified Smack label. Write a long format access rule to this file. The next read will indicate whether the access would be permitted. The text will be either "1" indicating access, or "0" indicating denial. ambient This contains the Smack label applied to unlabeled network packets. cipso This interface allows a specific CIPSO header to be assigned to a Smack label. The format accepted on write is: "%24s%4d%4d"["%4d"]... The first string is a fixed Smack label. The first number is the level to use. The second number is the number of categories. The following numbers are the categories. "level-3-cats-5-19 3 2 5 19" cipso2 This interface allows a specific CIPSO header to be assigned to a Smack label. The format accepted on write is: "%s%4d%4d"["%4d"]... The first string is a long Smack label. The first number is the level to use. The second number is the number of categories. The following numbers are the categories. "level-3-cats-5-19 3 2 5 19" direct This contains the CIPSO level used for Smack direct label representation in network packets. doi This contains the CIPSO domain of interpretation used in network packets. load This interface allows access control rules in addition to the system defined rules to be specified. The format accepted on write is: "%24s%24s%5s" where the first string is the subject label, the second the object label, and the third the requested access. The access string may contain only the characters "rwxat-", and specifies which sort of access is allowed. The "-" is a placeholder for permissions that are not allowed. The string "r-x--" would specify read and execute access. Labels are limited to 23 characters in length. load2 This interface allows access control rules in addition to the system defined rules to be specified. The format accepted on write is: "%s %s %s" where the first string is the subject label, the second the object label, and the third the requested access. The access string may contain only the characters "rwxat-", and specifies which sort of access is allowed. The "-" is a placeholder for permissions that are not allowed. The string "r-x--" would specify read and execute access. load-self This interface allows process specific access rules to be defined. These rules are only consulted if access would otherwise be permitted, and are intended to provide additional restrictions on the process. The format is the same as for the load interface. load-self2 This interface allows process specific access rules to be defined. These rules are only consulted if access would otherwise be permitted, and are intended to provide additional restrictions on the process. The format is the same as for the load2 interface. logging This contains the Smack logging state. mapped This contains the CIPSO level used for Smack mapped label representation in network packets. netlabel This interface allows specific internet addresses to be treated as single label hosts. Packets are sent to single label hosts without CIPSO headers, but only from processes that have Smack write access to the host label. All packets received from single label hosts are given the specified label. The format accepted on write is: "%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label". onlycap This contains the label processes must have for CAP_MAC_ADMIN and CAP_MAC_OVERRIDE to be effective. If this file is empty these capabilities are effective at for processes with any label. The value is set by writing the desired label to the file or cleared by writing "-" to the file. You can add access rules in /etc/smack/accesses. They take the form: You can add access rules in /etc/smack/accesses. They take the form: Loading @@ -83,10 +203,6 @@ access is a combination of the letters rwxa which specify the kind of access permitted a subject with subjectlabel on an kind of access permitted a subject with subjectlabel on an object with objectlabel. If there is no rule no access is allowed. object with objectlabel. If there is no rule no access is allowed. A process can see the smack label it is running with by reading /proc/self/attr/current. A privileged process can set the process smack by writing there. Look for additional programs on http://schaufler-ca.com Look for additional programs on http://schaufler-ca.com From the Smack Whitepaper: From the Smack Whitepaper: Loading Loading @@ -186,7 +302,7 @@ team. Smack labels are unstructured, case sensitive, and the only operation ever performed on them is comparison for equality. Smack labels cannot ever performed on them is comparison for equality. Smack labels cannot contain unprintable characters, the "/" (slash), the "\" (backslash), the "'" contain unprintable characters, the "/" (slash), the "\" (backslash), the "'" (quote) and '"' (double-quote) characters. (quote) and '"' (double-quote) characters. Smack labels cannot begin with a '-', which is reserved for special options. Smack labels cannot begin with a '-'. This is reserved for special options. There are some predefined labels: There are some predefined labels: Loading @@ -194,7 +310,7 @@ There are some predefined labels: ^ Pronounced "hat", a single circumflex character. ^ Pronounced "hat", a single circumflex character. * Pronounced "star", a single asterisk character. * Pronounced "star", a single asterisk character. ? Pronounced "huh", a single question mark character. ? Pronounced "huh", a single question mark character. @ Pronounced "Internet", a single at sign character. @ Pronounced "web", a single at sign character. Every task on a Smack system is assigned a label. System tasks, such as Every task on a Smack system is assigned a label. System tasks, such as init(8) and systems daemons, are run with the floor ("_") label. User tasks init(8) and systems daemons, are run with the floor ("_") label. User tasks Loading Loading @@ -246,13 +362,14 @@ The format of an access rule is: Where subject-label is the Smack label of the task, object-label is the Smack Where subject-label is the Smack label of the task, object-label is the Smack label of the thing being accessed, and access is a string specifying the sort label of the thing being accessed, and access is a string specifying the sort of access allowed. The Smack labels are limited to 23 characters. The access of access allowed. The access specification is searched for letters that specification is searched for letters that describe access modes: describe access modes: a: indicates that append access should be granted. a: indicates that append access should be granted. r: indicates that read access should be granted. r: indicates that read access should be granted. w: indicates that write access should be granted. w: indicates that write access should be granted. x: indicates that execute access should be granted. x: indicates that execute access should be granted. t: indicates that the rule requests transmutation. Uppercase values for the specification letters are allowed as well. Uppercase values for the specification letters are allowed as well. Access mode specifications can be in any order. Examples of acceptable rules Access mode specifications can be in any order. Examples of acceptable rules Loading @@ -273,7 +390,7 @@ Examples of unacceptable rules are: Spaces are not allowed in labels. Since a subject always has access to files Spaces are not allowed in labels. Since a subject always has access to files with the same label specifying a rule for that case is pointless. Only with the same label specifying a rule for that case is pointless. Only valid letters (rwxaRWXA) and the dash ('-') character are allowed in valid letters (rwxatRWXAT) and the dash ('-') character are allowed in access specifications. The dash is a placeholder, so "a-r" is the same access specifications. The dash is a placeholder, so "a-r" is the same as "ar". A lone dash is used to specify that no access should be allowed. as "ar". A lone dash is used to specify that no access should be allowed. Loading @@ -297,6 +414,13 @@ but not any of its attributes by the circumstance of having read access to the containing directory but not to the differently labeled file. This is an containing directory but not to the differently labeled file. This is an artifact of the file name being data in the directory, not a part of the file. artifact of the file name being data in the directory, not a part of the file. If a directory is marked as transmuting (SMACK64TRANSMUTE=TRUE) and the access rule that allows a process to create an object in that directory includes 't' access the label assigned to the new object will be that of the directory, not the creating process. This makes it much easier for two processes with different labels to share data without granting access to all of their files. IPC objects, message queues, semaphore sets, and memory segments exist in flat IPC objects, message queues, semaphore sets, and memory segments exist in flat namespaces and access requests are only required to match the object in namespaces and access requests are only required to match the object in question. question. Loading
security/smack/smack.h +21 −36 Original line number Original line Diff line number Diff line Loading @@ -23,13 +23,19 @@ #include <linux/lsm_audit.h> #include <linux/lsm_audit.h> /* /* * Smack labels were limited to 23 characters for a long time. */ #define SMK_LABELLEN 24 #define SMK_LONGLABEL 256 /* * 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 * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is * bigger than can be used, and 24 is the next lower multiple * bigger than can be used, and 24 is the next lower multiple * of 8, and there are too many issues if there isn't space set * of 8, and there are too many issues if there isn't space set * aside for the terminating null byte. * aside for the terminating null byte. */ */ #define SMK_MAXLEN 23 #define SMK_CIPSOLEN 24 #define SMK_LABELLEN (SMK_MAXLEN+1) struct superblock_smack { struct superblock_smack { char *smk_root; char *smk_root; Loading Loading @@ -66,6 +72,7 @@ struct task_smack { #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ #define SMK_INODE_CHANGED 0x04 /* smack was transmuted */ /* /* * A label access rule. * A label access rule. Loading @@ -77,15 +84,6 @@ struct smack_rule { int smk_access; int smk_access; }; }; /* * An entry in the table mapping smack values to * CIPSO level/category-set values. */ struct smack_cipso { int smk_level; char smk_catset[SMK_LABELLEN]; }; /* /* * An entry in the table identifying hosts. * An entry in the table identifying hosts. */ */ Loading Loading @@ -113,9 +111,7 @@ struct smk_netlbladdr { * interfaces don't. The secid should go away when all of * interfaces don't. The secid should go away when all of * these components have been repaired. * these components have been repaired. * * * If there is a cipso value associated with the label it * The cipso value associated with the label gets stored here, too. * gets stored here, too. This will most likely be rare as * the cipso direct mapping in used internally. * * * Keep the access rules for this subject label here so that * Keep the access rules for this subject label here so that * the entire set of rules does not need to be examined every * the entire set of rules does not need to be examined every Loading @@ -123,12 +119,11 @@ struct smk_netlbladdr { */ */ struct smack_known { struct smack_known { struct list_head list; struct list_head list; char smk_known[SMK_LABELLEN]; char *smk_known; u32 smk_secid; u32 smk_secid; struct smack_cipso *smk_cipso; struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */ spinlock_t smk_cipsolock; /* for changing cipso map */ struct list_head smk_rules; /* access rules */ struct list_head smk_rules; /* access rules */ struct mutex smk_rules_lock; /* lock for the rules */ struct mutex smk_rules_lock; /* lock for rules */ }; }; /* /* Loading Loading @@ -165,6 +160,7 @@ struct smack_known { #define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ #define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ #define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */ #define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */ #define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */ #define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */ #define SMACK_CIPSO_MAPPED_DEFAULT 251 /* Also arbitrary */ #define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */ #define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */ #define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */ #define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */ #define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ #define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ Loading Loading @@ -215,10 +211,9 @@ struct inode_smack *new_inode_smack(char *); int smk_access_entry(char *, char *, struct list_head *); int smk_access_entry(char *, char *, struct list_head *); int smk_access(char *, char *, int, struct smk_audit_info *); int smk_access(char *, char *, int, struct smk_audit_info *); int smk_curacc(char *, u32, struct smk_audit_info *); int smk_curacc(char *, u32, struct smk_audit_info *); int smack_to_cipso(const char *, struct smack_cipso *); char *smack_from_cipso(u32, char *); char *smack_from_secid(const u32); char *smack_from_secid(const u32); void smk_parse_smack(const char *string, int len, char *smack); char *smk_parse_smack(const char *string, int len); int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); char *smk_import(const char *, int); char *smk_import(const char *, int); struct smack_known *smk_import_entry(const char *, int); struct smack_known *smk_import_entry(const char *, int); struct smack_known *smk_find_entry(const char *); struct smack_known *smk_find_entry(const char *); Loading @@ -228,6 +223,7 @@ u32 smack_to_secid(const char *); * Shared data. * Shared data. */ */ extern int smack_cipso_direct; extern int smack_cipso_direct; extern int smack_cipso_mapped; extern char *smack_net_ambient; extern char *smack_net_ambient; extern char *smack_onlycap; extern char *smack_onlycap; extern const char *smack_cipso_option; extern const char *smack_cipso_option; Loading @@ -239,23 +235,12 @@ extern struct smack_known smack_known_invalid; extern struct smack_known smack_known_star; extern struct smack_known smack_known_star; extern struct smack_known smack_known_web; extern struct smack_known smack_known_web; extern struct mutex smack_known_lock; extern struct list_head smack_known_list; extern struct list_head smack_known_list; extern struct list_head smk_netlbladdr_list; extern struct list_head smk_netlbladdr_list; extern struct security_operations smack_ops; extern struct security_operations smack_ops; /* * Stricly for CIPSO level manipulation. * Set the category bit number in a smack label sized buffer. */ static inline void smack_catset_bit(int cat, char *catsetp) { if (cat > SMK_LABELLEN * 8) return; catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8); } /* /* * Is the directory transmuting? * Is the directory transmuting? */ */ Loading
security/smack/smack_access.c +116 −117 Original line number Original line Diff line number Diff line Loading @@ -19,37 +19,31 @@ struct smack_known smack_known_huh = { struct smack_known smack_known_huh = { .smk_known = "?", .smk_known = "?", .smk_secid = 2, .smk_secid = 2, .smk_cipso = NULL, }; }; struct smack_known smack_known_hat = { struct smack_known smack_known_hat = { .smk_known = "^", .smk_known = "^", .smk_secid = 3, .smk_secid = 3, .smk_cipso = NULL, }; }; struct smack_known smack_known_star = { struct smack_known smack_known_star = { .smk_known = "*", .smk_known = "*", .smk_secid = 4, .smk_secid = 4, .smk_cipso = NULL, }; }; struct smack_known smack_known_floor = { struct smack_known smack_known_floor = { .smk_known = "_", .smk_known = "_", .smk_secid = 5, .smk_secid = 5, .smk_cipso = NULL, }; }; struct smack_known smack_known_invalid = { struct smack_known smack_known_invalid = { .smk_known = "", .smk_known = "", .smk_secid = 6, .smk_secid = 6, .smk_cipso = NULL, }; }; struct smack_known smack_known_web = { struct smack_known smack_known_web = { .smk_known = "@", .smk_known = "@", .smk_secid = 7, .smk_secid = 7, .smk_cipso = NULL, }; }; LIST_HEAD(smack_known_list); LIST_HEAD(smack_known_list); Loading Loading @@ -331,7 +325,7 @@ void smack_log(char *subject_label, char *object_label, int request, } } #endif #endif static DEFINE_MUTEX(smack_known_lock); DEFINE_MUTEX(smack_known_lock); /** /** * smk_find_entry - find a label on the list, return the list entry * smk_find_entry - find a label on the list, return the list entry Loading @@ -345,7 +339,7 @@ struct smack_known *smk_find_entry(const char *string) struct smack_known *skp; struct smack_known *skp; list_for_each_entry_rcu(skp, &smack_known_list, list) { list_for_each_entry_rcu(skp, &smack_known_list, list) { if (strncmp(skp->smk_known, string, SMK_MAXLEN) == 0) if (strcmp(skp->smk_known, string) == 0) return skp; return skp; } } Loading @@ -356,27 +350,76 @@ struct smack_known *smk_find_entry(const char *string) * smk_parse_smack - parse smack label from a text string * smk_parse_smack - parse smack label from a text string * @string: a text string that might contain a Smack label * @string: a text string that might contain a Smack label * @len: the maximum size, or zero if it is NULL terminated. * @len: the maximum size, or zero if it is NULL terminated. * @smack: parsed smack label, or NULL if parse error * * Returns a pointer to the clean label, or NULL */ */ void smk_parse_smack(const char *string, int len, char *smack) char *smk_parse_smack(const char *string, int len) { { int found; char *smack; int i; int i; if (len <= 0 || len > SMK_MAXLEN) if (len <= 0) len = SMK_MAXLEN; len = strlen(string) + 1; for (i = 0, found = 0; i < SMK_LABELLEN; i++) { /* if (found) * Reserve a leading '-' as an indicator that smack[i] = '\0'; * this isn't a label, but an option to interfaces else if (i >= len || string[i] > '~' || string[i] <= ' ' || * including /smack/cipso and /smack/cipso2 string[i] == '/' || string[i] == '"' || */ string[i] == '\\' || string[i] == '\'') { if (string[0] == '-') return NULL; for (i = 0; i < len; i++) if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' || string[i] == '"' || string[i] == '\\' || string[i] == '\'') break; if (i == 0 || i >= SMK_LONGLABEL) return NULL; smack = kzalloc(i + 1, GFP_KERNEL); if (smack != NULL) { strncpy(smack, string, i + 1); smack[i] = '\0'; smack[i] = '\0'; found = 1; } else smack[i] = string[i]; } } return smack; } /** * smk_netlbl_mls - convert a catset to netlabel mls categories * @catset: the Smack categories * @sap: where to put the netlabel categories * * Allocates and fills attr.mls * Returns 0 on success, error code on failure. */ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap, int len) { unsigned char *cp; unsigned char m; int cat; int rc; int byte; sap->flags |= NETLBL_SECATTR_MLS_CAT; sap->attr.mls.lvl = level; sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); sap->attr.mls.cat->startbit = 0; for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++) for (m = 0x80; m != 0; m >>= 1, cat++) { if ((m & *cp) == 0) continue; rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat, cat, GFP_ATOMIC); if (rc < 0) { netlbl_secattr_catmap_free(sap->attr.mls.cat); return rc; } } return 0; } } /** /** Loading @@ -390,33 +433,59 @@ void smk_parse_smack(const char *string, int len, char *smack) struct smack_known *smk_import_entry(const char *string, int len) struct smack_known *smk_import_entry(const char *string, int len) { { struct smack_known *skp; struct smack_known *skp; char smack[SMK_LABELLEN]; char *smack; int slen; int rc; smk_parse_smack(string, len, smack); smack = smk_parse_smack(string, len); if (smack[0] == '\0') if (smack == NULL) return NULL; return NULL; mutex_lock(&smack_known_lock); mutex_lock(&smack_known_lock); skp = smk_find_entry(smack); skp = smk_find_entry(smack); if (skp != NULL) goto freeout; if (skp == NULL) { skp = kzalloc(sizeof(*skp), GFP_KERNEL); skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL); if (skp == NULL) if (skp != NULL) { goto freeout; strncpy(skp->smk_known, smack, SMK_MAXLEN); skp->smk_known = smack; skp->smk_secid = smack_next_secid++; skp->smk_secid = smack_next_secid++; skp->smk_cipso = NULL; skp->smk_netlabel.domain = skp->smk_known; skp->smk_netlabel.flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; /* * If direct labeling works use it. * Otherwise use mapped labeling. */ slen = strlen(smack); if (slen < SMK_CIPSOLEN) rc = smk_netlbl_mls(smack_cipso_direct, skp->smk_known, &skp->smk_netlabel, slen); else rc = smk_netlbl_mls(smack_cipso_mapped, (char *)&skp->smk_secid, &skp->smk_netlabel, sizeof(skp->smk_secid)); if (rc >= 0) { INIT_LIST_HEAD(&skp->smk_rules); INIT_LIST_HEAD(&skp->smk_rules); spin_lock_init(&skp->smk_cipsolock); mutex_init(&skp->smk_rules_lock); mutex_init(&skp->smk_rules_lock); /* /* * Make sure that the entry is actually * Make sure that the entry is actually * filled before putting it on the list. * filled before putting it on the list. */ */ list_add_rcu(&skp->list, &smack_known_list); list_add_rcu(&skp->list, &smack_known_list); goto unlockout; } } } /* * smk_netlbl_mls failed. */ kfree(skp); skp = NULL; freeout: kfree(smack); unlockout: mutex_unlock(&smack_known_lock); mutex_unlock(&smack_known_lock); return skp; return skp; Loading Loading @@ -479,79 +548,9 @@ char *smack_from_secid(const u32 secid) */ */ u32 smack_to_secid(const char *smack) u32 smack_to_secid(const char *smack) { { struct smack_known *skp; struct smack_known *skp = smk_find_entry(smack); rcu_read_lock(); list_for_each_entry_rcu(skp, &smack_known_list, list) { if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) { rcu_read_unlock(); return skp->smk_secid; } } rcu_read_unlock(); return 0; } /** * smack_from_cipso - find the Smack label associated with a CIPSO option * @level: Bell & LaPadula level from the network * @cp: Bell & LaPadula categories from the network * * This is a simple lookup in the label table. * * Return the matching label from the label list or NULL. */ char *smack_from_cipso(u32 level, char *cp) { struct smack_known *kp; char *final = NULL; rcu_read_lock(); list_for_each_entry(kp, &smack_known_list, list) { if (kp->smk_cipso == NULL) continue; spin_lock_bh(&kp->smk_cipsolock); if (kp->smk_cipso->smk_level == level && memcmp(kp->smk_cipso->smk_catset, cp, SMK_LABELLEN) == 0) final = kp->smk_known; spin_unlock_bh(&kp->smk_cipsolock); if (skp == NULL) if (final != NULL) break; } rcu_read_unlock(); return final; } /** * smack_to_cipso - find the CIPSO option to go with a Smack label * @smack: a pointer to the smack label in question * @cp: where to put the result * * Returns zero if a value is available, non-zero otherwise. */ int smack_to_cipso(const char *smack, struct smack_cipso *cp) { struct smack_known *kp; int found = 0; rcu_read_lock(); list_for_each_entry_rcu(kp, &smack_known_list, list) { if (kp->smk_known == smack || strcmp(kp->smk_known, smack) == 0) { found = 1; break; } } rcu_read_unlock(); if (found == 0 || kp->smk_cipso == NULL) return -ENOENT; memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso)); return 0; return 0; return skp->smk_secid; } }