Skip to content

Commit

Permalink
Merge branch 'smack-for-4.2-stacked' of https://github.com/cschaufler…
Browse files Browse the repository at this point in the history
…/smack-next into next
  • Loading branch information
James Morris committed Jun 3, 2015
2 parents 8d94eb9 + c0d77c8 commit e6e29a4
Show file tree
Hide file tree
Showing 5 changed files with 317 additions and 189 deletions.
6 changes: 3 additions & 3 deletions Documentation/security/Smack.txt
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,11 @@ netlabel
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
This contains labels 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.
label. The values are set by writing the desired labels, separated
by spaces, to the file or cleared by writing "-" to the file.
ptrace
This is used to define the current ptrace policy
0 - default: this is the policy that relies on Smack access rules.
Expand Down
25 changes: 9 additions & 16 deletions security/smack/smack.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ struct smk_port_label {
struct smack_known *smk_out; /* outgoing label */
};

struct smack_onlycap {
struct list_head list;
struct smack_known *smk_label;
};

/*
* Mount options
*/
Expand Down Expand Up @@ -249,6 +254,7 @@ int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
struct smack_known *smk_import_entry(const char *, int);
void smk_insert_entry(struct smack_known *skp);
struct smack_known *smk_find_entry(const char *);
int smack_privileged(int cap);

/*
* Shared data.
Expand All @@ -257,7 +263,6 @@ extern int smack_enabled;
extern int smack_cipso_direct;
extern int smack_cipso_mapped;
extern struct smack_known *smack_net_ambient;
extern struct smack_known *smack_onlycap;
extern struct smack_known *smack_syslog_label;
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
extern struct smack_known *smack_unconfined;
Expand All @@ -276,6 +281,9 @@ extern struct mutex smack_known_lock;
extern struct list_head smack_known_list;
extern struct list_head smk_netlbladdr_list;

extern struct mutex smack_onlycap_lock;
extern struct list_head smack_onlycap_list;

#define SMACK_HASH_SLOTS 16
extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];

Expand Down Expand Up @@ -331,21 +339,6 @@ static inline struct smack_known *smk_of_current(void)
return smk_of_task(current_security());
}

/*
* Is the task privileged and allowed to be privileged
* by the onlycap rule.
*/
static inline int smack_privileged(int cap)
{
struct smack_known *skp = smk_of_current();

if (!capable(cap))
return 0;
if (smack_onlycap == NULL || smack_onlycap == skp)
return 1;
return 0;
}

/*
* logging functions
*/
Expand Down
68 changes: 57 additions & 11 deletions security/smack/smack_access.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ void smk_insert_entry(struct smack_known *skp)
* @string: a text string that might be a Smack label
*
* Returns a pointer to the entry in the label list that
* matches the passed string.
* matches the passed string or NULL if not found.
*/
struct smack_known *smk_find_entry(const char *string)
{
Expand All @@ -448,7 +448,7 @@ struct smack_known *smk_find_entry(const char *string)
* @string: a text string that might contain a Smack label
* @len: the maximum size, or zero if it is NULL terminated.
*
* Returns a pointer to the clean label, or NULL
* Returns a pointer to the clean label or an error code.
*/
char *smk_parse_smack(const char *string, int len)
{
Expand All @@ -464,19 +464,21 @@ char *smk_parse_smack(const char *string, int len)
* including /smack/cipso and /smack/cipso2
*/
if (string[0] == '-')
return NULL;
return ERR_PTR(-EINVAL);

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;
return ERR_PTR(-EINVAL);

smack = kzalloc(i + 1, GFP_KERNEL);
if (smack != NULL)
strncpy(smack, string, i);
if (smack == NULL)
return ERR_PTR(-ENOMEM);

strncpy(smack, string, i);

return smack;
}
Expand Down Expand Up @@ -523,7 +525,8 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
* @len: the maximum size, or zero if it is NULL terminated.
*
* Returns a pointer to the entry in the label list that
* matches the passed string, adding it if necessary.
* matches the passed string, adding it if necessary,
* or an error code.
*/
struct smack_known *smk_import_entry(const char *string, int len)
{
Expand All @@ -533,8 +536,8 @@ struct smack_known *smk_import_entry(const char *string, int len)
int rc;

smack = smk_parse_smack(string, len);
if (smack == NULL)
return NULL;
if (IS_ERR(smack))
return ERR_CAST(smack);

mutex_lock(&smack_known_lock);

Expand All @@ -543,8 +546,10 @@ struct smack_known *smk_import_entry(const char *string, int len)
goto freeout;

skp = kzalloc(sizeof(*skp), GFP_KERNEL);
if (skp == NULL)
if (skp == NULL) {
skp = ERR_PTR(-ENOMEM);
goto freeout;
}

skp->smk_known = smack;
skp->smk_secid = smack_next_secid++;
Expand Down Expand Up @@ -577,7 +582,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
* smk_netlbl_mls failed.
*/
kfree(skp);
skp = NULL;
skp = ERR_PTR(rc);
freeout:
kfree(smack);
unlockout:
Expand Down Expand Up @@ -612,3 +617,44 @@ struct smack_known *smack_from_secid(const u32 secid)
rcu_read_unlock();
return &smack_known_invalid;
}

/*
* Unless a process is running with one of these labels
* even having CAP_MAC_OVERRIDE isn't enough to grant
* privilege to violate MAC policy. If no labels are
* designated (the empty list case) capabilities apply to
* everyone.
*/
LIST_HEAD(smack_onlycap_list);
DEFINE_MUTEX(smack_onlycap_lock);

/*
* Is the task privileged and allowed to be privileged
* by the onlycap rule.
*
* Returns 1 if the task is allowed to be privileged, 0 if it's not.
*/
int smack_privileged(int cap)
{
struct smack_known *skp = smk_of_current();
struct smack_onlycap *sop;

if (!capable(cap))
return 0;

rcu_read_lock();
if (list_empty(&smack_onlycap_list)) {
rcu_read_unlock();
return 1;
}

list_for_each_entry_rcu(sop, &smack_onlycap_list, list) {
if (sop->smk_label == skp) {
rcu_read_unlock();
return 1;
}
}
rcu_read_unlock();

return 0;
}
Loading

0 comments on commit e6e29a4

Please sign in to comment.