Merge branch 'for-1205' of http://git.gitorious.org/smack-next/kernel into next
Pull request from Casey.
This commit is contained in:
commit
12fa8a2732
5 changed files with 1160 additions and 594 deletions
|
@ -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
|
||||||
|
@ -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
|
git@gitorious.org:meego-platform-security/smackutil.git
|
||||||
Smack labels on long listing is available.
|
git@gitorious.org:meego-platform-security/libsmack.git
|
||||||
|
|
||||||
A hacked version of sshd that allows network logins by users
|
These should make and install on most modern distributions.
|
||||||
with specific Smack labels is available. This version does
|
There are three commands included in smackutil:
|
||||||
not work for scp. You must set the /etc/ssh/sshd_config
|
|
||||||
line:
|
|
||||||
UsePrivilegeSeparation no
|
|
||||||
|
|
||||||
The format of /etc/smack/usr is:
|
smackload - properly formats data for writing to /smack/load
|
||||||
|
smackcipso - properly formats data for writing to /smack/cipso
|
||||||
username smack
|
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:
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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:
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -113,22 +111,19 @@ 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
|
||||||
* time.
|
* time.
|
||||||
*/
|
*/
|
||||||
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 rules */
|
||||||
struct mutex smk_rules_lock; /* lock for the rules */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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 */
|
||||||
|
@ -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 *);
|
||||||
|
@ -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;
|
||||||
|
@ -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?
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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] == '-')
|
||||||
smack[i] = '\0';
|
return NULL;
|
||||||
found = 1;
|
|
||||||
} else
|
for (i = 0; i < len; i++)
|
||||||
smack[i] = string[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';
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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_secid = smack_next_secid++;
|
skp->smk_known = smack;
|
||||||
skp->smk_cipso = NULL;
|
skp->smk_secid = smack_next_secid++;
|
||||||
INIT_LIST_HEAD(&skp->smk_rules);
|
skp->smk_netlabel.domain = skp->smk_known;
|
||||||
spin_lock_init(&skp->smk_cipsolock);
|
skp->smk_netlabel.flags =
|
||||||
mutex_init(&skp->smk_rules_lock);
|
NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
|
||||||
/*
|
/*
|
||||||
* Make sure that the entry is actually
|
* If direct labeling works use it.
|
||||||
* filled before putting it on the list.
|
* Otherwise use mapped labeling.
|
||||||
*/
|
*/
|
||||||
list_add_rcu(&skp->list, &smack_known_list);
|
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);
|
||||||
|
mutex_init(&skp->smk_rules_lock);
|
||||||
|
/*
|
||||||
|
* Make sure that the entry is actually
|
||||||
|
* filled before putting it on the 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;
|
||||||
|
@ -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();
|
if (skp == NULL)
|
||||||
list_for_each_entry_rcu(skp, &smack_known_list, list) {
|
return 0;
|
||||||
if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
|
return skp->smk_secid;
|
||||||
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 (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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/pipe_fs_i.h>
|
#include <linux/pipe_fs_i.h>
|
||||||
#include <net/netlabel.h>
|
|
||||||
#include <net/cipso_ipv4.h>
|
#include <net/cipso_ipv4.h>
|
||||||
#include <linux/audit.h>
|
#include <linux/audit.h>
|
||||||
#include <linux/magic.h>
|
#include <linux/magic.h>
|
||||||
|
@ -57,16 +56,23 @@
|
||||||
static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp)
|
static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
char in[SMK_LABELLEN];
|
char *buffer;
|
||||||
|
char *result = NULL;
|
||||||
|
|
||||||
if (ip->i_op->getxattr == NULL)
|
if (ip->i_op->getxattr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
rc = ip->i_op->getxattr(dp, name, in, SMK_LABELLEN);
|
buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
|
||||||
if (rc < 0)
|
if (buffer == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return smk_import(in, rc);
|
rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL);
|
||||||
|
if (rc > 0)
|
||||||
|
result = smk_import(buffer, rc);
|
||||||
|
|
||||||
|
kfree(buffer);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,7 +85,7 @@ struct inode_smack *new_inode_smack(char *smack)
|
||||||
{
|
{
|
||||||
struct inode_smack *isp;
|
struct inode_smack *isp;
|
||||||
|
|
||||||
isp = kzalloc(sizeof(struct inode_smack), GFP_KERNEL);
|
isp = kzalloc(sizeof(struct inode_smack), GFP_NOFS);
|
||||||
if (isp == NULL)
|
if (isp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -556,13 +562,14 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
|
||||||
void **value, size_t *len)
|
void **value, size_t *len)
|
||||||
{
|
{
|
||||||
struct smack_known *skp;
|
struct smack_known *skp;
|
||||||
|
struct inode_smack *issp = inode->i_security;
|
||||||
char *csp = smk_of_current();
|
char *csp = smk_of_current();
|
||||||
char *isp = smk_of_inode(inode);
|
char *isp = smk_of_inode(inode);
|
||||||
char *dsp = smk_of_inode(dir);
|
char *dsp = smk_of_inode(dir);
|
||||||
int may;
|
int may;
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
*name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL);
|
*name = kstrdup(XATTR_SMACK_SUFFIX, GFP_NOFS);
|
||||||
if (*name == NULL)
|
if (*name == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -577,12 +584,15 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
|
||||||
* If the access rule allows transmutation and
|
* If the access rule allows transmutation and
|
||||||
* the directory requests transmutation then
|
* the directory requests transmutation then
|
||||||
* by all means transmute.
|
* by all means transmute.
|
||||||
|
* Mark the inode as changed.
|
||||||
*/
|
*/
|
||||||
if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
|
if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
|
||||||
smk_inode_transmutable(dir))
|
smk_inode_transmutable(dir)) {
|
||||||
isp = dsp;
|
isp = dsp;
|
||||||
|
issp->smk_flags |= SMK_INODE_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
*value = kstrdup(isp, GFP_KERNEL);
|
*value = kstrdup(isp, GFP_NOFS);
|
||||||
if (*value == NULL)
|
if (*value == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -821,7 +831,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
|
||||||
* check label validity here so import wont fail on
|
* check label validity here so import wont fail on
|
||||||
* post_setxattr
|
* post_setxattr
|
||||||
*/
|
*/
|
||||||
if (size == 0 || size >= SMK_LABELLEN ||
|
if (size == 0 || size >= SMK_LONGLABEL ||
|
||||||
smk_import(value, size) == NULL)
|
smk_import(value, size) == NULL)
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
|
} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
|
||||||
|
@ -1819,65 +1829,6 @@ static char *smack_host_label(struct sockaddr_in *sip)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* smack_set_catset - convert a capset to netlabel mls categories
|
|
||||||
* @catset: the Smack categories
|
|
||||||
* @sap: where to put the netlabel categories
|
|
||||||
*
|
|
||||||
* Allocates and fills attr.mls.cat
|
|
||||||
*/
|
|
||||||
static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap)
|
|
||||||
{
|
|
||||||
unsigned char *cp;
|
|
||||||
unsigned char m;
|
|
||||||
int cat;
|
|
||||||
int rc;
|
|
||||||
int byte;
|
|
||||||
|
|
||||||
if (!catset)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sap->flags |= NETLBL_SECATTR_MLS_CAT;
|
|
||||||
sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
|
|
||||||
sap->attr.mls.cat->startbit = 0;
|
|
||||||
|
|
||||||
for (cat = 1, cp = catset, byte = 0; byte < SMK_LABELLEN; 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* smack_to_secattr - fill a secattr from a smack value
|
|
||||||
* @smack: the smack value
|
|
||||||
* @nlsp: where the result goes
|
|
||||||
*
|
|
||||||
* Casey says that CIPSO is good enough for now.
|
|
||||||
* It can be used to effect.
|
|
||||||
* It can also be abused to effect when necessary.
|
|
||||||
* Apologies to the TSIG group in general and GW in particular.
|
|
||||||
*/
|
|
||||||
static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
|
|
||||||
{
|
|
||||||
struct smack_cipso cipso;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
nlsp->domain = smack;
|
|
||||||
nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
|
|
||||||
|
|
||||||
rc = smack_to_cipso(smack, &cipso);
|
|
||||||
if (rc == 0) {
|
|
||||||
nlsp->attr.mls.lvl = cipso.smk_level;
|
|
||||||
smack_set_catset(cipso.smk_catset, nlsp);
|
|
||||||
} else {
|
|
||||||
nlsp->attr.mls.lvl = smack_cipso_direct;
|
|
||||||
smack_set_catset(smack, nlsp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_netlabel - Set the secattr on a socket
|
* smack_netlabel - Set the secattr on a socket
|
||||||
* @sk: the socket
|
* @sk: the socket
|
||||||
|
@ -1890,8 +1841,8 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
|
||||||
*/
|
*/
|
||||||
static int smack_netlabel(struct sock *sk, int labeled)
|
static int smack_netlabel(struct sock *sk, int labeled)
|
||||||
{
|
{
|
||||||
|
struct smack_known *skp;
|
||||||
struct socket_smack *ssp = sk->sk_security;
|
struct socket_smack *ssp = sk->sk_security;
|
||||||
struct netlbl_lsm_secattr secattr;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1909,10 +1860,8 @@ static int smack_netlabel(struct sock *sk, int labeled)
|
||||||
labeled == SMACK_UNLABELED_SOCKET)
|
labeled == SMACK_UNLABELED_SOCKET)
|
||||||
netlbl_sock_delattr(sk);
|
netlbl_sock_delattr(sk);
|
||||||
else {
|
else {
|
||||||
netlbl_secattr_init(&secattr);
|
skp = smk_find_entry(ssp->smk_out);
|
||||||
smack_to_secattr(ssp->smk_out, &secattr);
|
rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
|
||||||
rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr);
|
|
||||||
netlbl_secattr_destroy(&secattr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bh_unlock_sock(sk);
|
bh_unlock_sock(sk);
|
||||||
|
@ -1985,7 +1934,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (value == NULL || size > SMK_LABELLEN || size == 0)
|
if (value == NULL || size > SMK_LONGLABEL || size == 0)
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
|
||||||
sp = smk_import(value, size);
|
sp = smk_import(value, size);
|
||||||
|
@ -2552,6 +2501,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
|
||||||
char *final;
|
char *final;
|
||||||
char trattr[TRANS_TRUE_SIZE];
|
char trattr[TRANS_TRUE_SIZE];
|
||||||
int transflag = 0;
|
int transflag = 0;
|
||||||
|
int rc;
|
||||||
struct dentry *dp;
|
struct dentry *dp;
|
||||||
|
|
||||||
if (inode == NULL)
|
if (inode == NULL)
|
||||||
|
@ -2670,17 +2620,38 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
|
||||||
*/
|
*/
|
||||||
dp = dget(opt_dentry);
|
dp = dget(opt_dentry);
|
||||||
fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp);
|
fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp);
|
||||||
if (fetched != NULL) {
|
if (fetched != NULL)
|
||||||
final = fetched;
|
final = fetched;
|
||||||
if (S_ISDIR(inode->i_mode)) {
|
|
||||||
trattr[0] = '\0';
|
/*
|
||||||
inode->i_op->getxattr(dp,
|
* Transmuting directory
|
||||||
|
*/
|
||||||
|
if (S_ISDIR(inode->i_mode)) {
|
||||||
|
/*
|
||||||
|
* If this is a new directory and the label was
|
||||||
|
* transmuted when the inode was initialized
|
||||||
|
* set the transmute attribute on the directory
|
||||||
|
* and mark the inode.
|
||||||
|
*
|
||||||
|
* If there is a transmute attribute on the
|
||||||
|
* directory mark the inode.
|
||||||
|
*/
|
||||||
|
if (isp->smk_flags & SMK_INODE_CHANGED) {
|
||||||
|
isp->smk_flags &= ~SMK_INODE_CHANGED;
|
||||||
|
rc = inode->i_op->setxattr(dp,
|
||||||
XATTR_NAME_SMACKTRANSMUTE,
|
XATTR_NAME_SMACKTRANSMUTE,
|
||||||
trattr, TRANS_TRUE_SIZE);
|
TRANS_TRUE, TRANS_TRUE_SIZE,
|
||||||
if (strncmp(trattr, TRANS_TRUE,
|
0);
|
||||||
TRANS_TRUE_SIZE) == 0)
|
} else {
|
||||||
transflag = SMK_INODE_TRANSMUTE;
|
rc = inode->i_op->getxattr(dp,
|
||||||
|
XATTR_NAME_SMACKTRANSMUTE, trattr,
|
||||||
|
TRANS_TRUE_SIZE);
|
||||||
|
if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
|
||||||
|
TRANS_TRUE_SIZE) != 0)
|
||||||
|
rc = -EINVAL;
|
||||||
}
|
}
|
||||||
|
if (rc >= 0)
|
||||||
|
transflag = SMK_INODE_TRANSMUTE;
|
||||||
}
|
}
|
||||||
isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
|
isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
|
||||||
isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
|
isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
|
||||||
|
@ -2759,7 +2730,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
|
||||||
if (!capable(CAP_MAC_ADMIN))
|
if (!capable(CAP_MAC_ADMIN))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
if (value == NULL || size == 0 || size >= SMK_LABELLEN)
|
if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (strcmp(name, "current") != 0)
|
if (strcmp(name, "current") != 0)
|
||||||
|
@ -2895,10 +2866,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
|
||||||
static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
|
static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
|
||||||
struct socket_smack *ssp)
|
struct socket_smack *ssp)
|
||||||
{
|
{
|
||||||
struct smack_known *skp;
|
struct smack_known *kp;
|
||||||
char smack[SMK_LABELLEN];
|
|
||||||
char *sp;
|
char *sp;
|
||||||
int pcat;
|
int found = 0;
|
||||||
|
|
||||||
if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
|
if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
|
||||||
/*
|
/*
|
||||||
|
@ -2906,59 +2876,27 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
|
||||||
* If there are flags but no level netlabel isn't
|
* If there are flags but no level netlabel isn't
|
||||||
* behaving the way we expect it to.
|
* behaving the way we expect it to.
|
||||||
*
|
*
|
||||||
* Get the categories, if any
|
* Look it up in the label table
|
||||||
* Without guidance regarding the smack value
|
* Without guidance regarding the smack value
|
||||||
* for the packet fall back on the network
|
* for the packet fall back on the network
|
||||||
* ambient value.
|
* ambient value.
|
||||||
*/
|
*/
|
||||||
memset(smack, '\0', SMK_LABELLEN);
|
rcu_read_lock();
|
||||||
if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0)
|
list_for_each_entry(kp, &smack_known_list, list) {
|
||||||
for (pcat = -1;;) {
|
if (sap->attr.mls.lvl != kp->smk_netlabel.attr.mls.lvl)
|
||||||
pcat = netlbl_secattr_catmap_walk(
|
continue;
|
||||||
sap->attr.mls.cat, pcat + 1);
|
if (memcmp(sap->attr.mls.cat,
|
||||||
if (pcat < 0)
|
kp->smk_netlabel.attr.mls.cat,
|
||||||
break;
|
SMK_CIPSOLEN) != 0)
|
||||||
smack_catset_bit(pcat, smack);
|
continue;
|
||||||
}
|
found = 1;
|
||||||
/*
|
break;
|
||||||
* If it is CIPSO using smack direct mapping
|
|
||||||
* we are already done. WeeHee.
|
|
||||||
*/
|
|
||||||
if (sap->attr.mls.lvl == smack_cipso_direct) {
|
|
||||||
/*
|
|
||||||
* The label sent is usually on the label list.
|
|
||||||
*
|
|
||||||
* If it is not we may still want to allow the
|
|
||||||
* delivery.
|
|
||||||
*
|
|
||||||
* If the recipient is accepting all packets
|
|
||||||
* because it is using the star ("*") label
|
|
||||||
* for SMACK64IPIN provide the web ("@") label
|
|
||||||
* so that a directed response will succeed.
|
|
||||||
* This is not very correct from a MAC point
|
|
||||||
* of view, but gets around the problem that
|
|
||||||
* locking prevents adding the newly discovered
|
|
||||||
* label to the list.
|
|
||||||
* The case where the recipient is not using
|
|
||||||
* the star label should obviously fail.
|
|
||||||
* The easy way to do this is to provide the
|
|
||||||
* star label as the subject label.
|
|
||||||
*/
|
|
||||||
skp = smk_find_entry(smack);
|
|
||||||
if (skp != NULL)
|
|
||||||
return skp->smk_known;
|
|
||||||
if (ssp != NULL &&
|
|
||||||
ssp->smk_in == smack_known_star.smk_known)
|
|
||||||
return smack_known_web.smk_known;
|
|
||||||
return smack_known_star.smk_known;
|
|
||||||
}
|
}
|
||||||
/*
|
rcu_read_unlock();
|
||||||
* Look it up in the supplied table if it is not
|
|
||||||
* a direct mapping.
|
if (found)
|
||||||
*/
|
return kp->smk_known;
|
||||||
sp = smack_from_cipso(sap->attr.mls.lvl, smack);
|
|
||||||
if (sp != NULL)
|
|
||||||
return sp;
|
|
||||||
if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known)
|
if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known)
|
||||||
return smack_known_web.smk_known;
|
return smack_known_web.smk_known;
|
||||||
return smack_known_star.smk_known;
|
return smack_known_star.smk_known;
|
||||||
|
@ -3158,11 +3096,13 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
||||||
struct request_sock *req)
|
struct request_sock *req)
|
||||||
{
|
{
|
||||||
u16 family = sk->sk_family;
|
u16 family = sk->sk_family;
|
||||||
|
struct smack_known *skp;
|
||||||
struct socket_smack *ssp = sk->sk_security;
|
struct socket_smack *ssp = sk->sk_security;
|
||||||
struct netlbl_lsm_secattr secattr;
|
struct netlbl_lsm_secattr secattr;
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
struct iphdr *hdr;
|
struct iphdr *hdr;
|
||||||
char *sp;
|
char *sp;
|
||||||
|
char *hsp;
|
||||||
int rc;
|
int rc;
|
||||||
struct smk_audit_info ad;
|
struct smk_audit_info ad;
|
||||||
#ifdef CONFIG_AUDIT
|
#ifdef CONFIG_AUDIT
|
||||||
|
@ -3209,16 +3149,14 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
||||||
hdr = ip_hdr(skb);
|
hdr = ip_hdr(skb);
|
||||||
addr.sin_addr.s_addr = hdr->saddr;
|
addr.sin_addr.s_addr = hdr->saddr;
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
if (smack_host_label(&addr) == NULL) {
|
hsp = smack_host_label(&addr);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
netlbl_secattr_init(&secattr);
|
|
||||||
smack_to_secattr(sp, &secattr);
|
if (hsp == NULL) {
|
||||||
rc = netlbl_req_setattr(req, &secattr);
|
skp = smk_find_entry(sp);
|
||||||
netlbl_secattr_destroy(&secattr);
|
rc = netlbl_req_setattr(req, &skp->smk_netlabel);
|
||||||
} else {
|
} else
|
||||||
rcu_read_unlock();
|
|
||||||
netlbl_req_delattr(req);
|
netlbl_req_delattr(req);
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -3400,7 +3338,7 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule,
|
||||||
char *rule = vrule;
|
char *rule = vrule;
|
||||||
|
|
||||||
if (!rule) {
|
if (!rule) {
|
||||||
audit_log(actx, GFP_KERNEL, AUDIT_SELINUX_ERR,
|
audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
|
||||||
"Smack: missing rule\n");
|
"Smack: missing rule\n");
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
@ -3642,15 +3580,6 @@ struct security_operations smack_ops = {
|
||||||
|
|
||||||
static __init void init_smack_known_list(void)
|
static __init void init_smack_known_list(void)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* Initialize CIPSO locks
|
|
||||||
*/
|
|
||||||
spin_lock_init(&smack_known_huh.smk_cipsolock);
|
|
||||||
spin_lock_init(&smack_known_hat.smk_cipsolock);
|
|
||||||
spin_lock_init(&smack_known_star.smk_cipsolock);
|
|
||||||
spin_lock_init(&smack_known_floor.smk_cipsolock);
|
|
||||||
spin_lock_init(&smack_known_invalid.smk_cipsolock);
|
|
||||||
spin_lock_init(&smack_known_web.smk_cipsolock);
|
|
||||||
/*
|
/*
|
||||||
* Initialize rule list locks
|
* Initialize rule list locks
|
||||||
*/
|
*/
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue