M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
config SECURITY_SMACK
bool "Simplified Mandatory Access Control Kernel Support"
depends on NETLABEL && SECURITY_NETWORK
default n
help
This selects the Simplified Mandatory Access Control Kernel.
Smack is useful for sensitivity, integrity, and a variety
of other mandatory security schemes.
If you are unsure how to answer this question, answer N.
+7
View File
@@ -0,0 +1,7 @@
#
# Makefile for the SMACK LSM
#
obj-$(CONFIG_SECURITY_SMACK) := smack.o
smack-y := smack_lsm.o smack_access.o smackfs.o
+394
View File
@@ -0,0 +1,394 @@
/*
* Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* Author:
* Casey Schaufler <casey@schaufler-ca.com>
*
*/
#ifndef _SECURITY_SMACK_H
#define _SECURITY_SMACK_H
#include <linux/capability.h>
#include <linux/spinlock.h>
#include <linux/security.h>
#include <linux/in.h>
#include <net/netlabel.h>
#include <linux/list.h>
#include <linux/rculist.h>
#include <linux/lsm_audit.h>
/*
* 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
* of 8, and there are too many issues if there isn't space set
* aside for the terminating null byte.
*/
#define SMK_MAXLEN 23
#define SMK_LABELLEN (SMK_MAXLEN+1)
struct superblock_smack {
char *smk_root;
char *smk_floor;
char *smk_hat;
char *smk_default;
int smk_initialized;
spinlock_t smk_sblock; /* for initialization */
};
struct socket_smack {
char *smk_out; /* outbound label */
char *smk_in; /* inbound label */
char *smk_packet; /* TCP peer label */
};
/*
* Inode smack data
*/
struct inode_smack {
char *smk_inode; /* label of the fso */
char *smk_task; /* label of the task */
char *smk_mmap; /* label of the mmap domain */
struct mutex smk_lock; /* initialization lock */
int smk_flags; /* smack inode flags */
};
struct task_smack {
char *smk_task; /* label for access control */
char *smk_forked; /* label when forked */
struct list_head smk_rules; /* per task access rules */
struct mutex smk_rules_lock; /* lock for the rules */
};
#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
#define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */
/*
* A label access rule.
*/
struct smack_rule {
struct list_head list;
char *smk_subject;
char *smk_object;
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.
*/
struct smk_netlbladdr {
struct list_head list;
struct sockaddr_in smk_host; /* network address */
struct in_addr smk_mask; /* network mask */
char *smk_label; /* label */
};
/*
* This is the repository for labels seen so that it is
* not necessary to keep allocating tiny chuncks of memory
* and so that they can be shared.
*
* Labels are never modified in place. Anytime a label
* is imported (e.g. xattrset on a file) the list is checked
* for it and it is added if it doesn't exist. The address
* is passed out in either case. Entries are added, but
* never deleted.
*
* Since labels are hanging around anyway it doesn't
* hurt to maintain a secid for those awkward situations
* where kernel components that ought to use LSM independent
* interfaces don't. The secid should go away when all of
* these components have been repaired.
*
* If there is a cipso value associated with the label it
* 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
* the entire set of rules does not need to be examined every
* time.
*/
struct smack_known {
struct list_head list;
char smk_known[SMK_LABELLEN];
u32 smk_secid;
struct smack_cipso *smk_cipso;
spinlock_t smk_cipsolock; /* for changing cipso map */
struct list_head smk_rules; /* access rules */
struct mutex smk_rules_lock; /* lock for the rules */
};
/*
* Mount options
*/
#define SMK_FSDEFAULT "smackfsdef="
#define SMK_FSFLOOR "smackfsfloor="
#define SMK_FSHAT "smackfshat="
#define SMK_FSROOT "smackfsroot="
#define SMACK_CIPSO_OPTION "-CIPSO"
/*
* How communications on this socket are treated.
* Usually it's determined by the underlying netlabel code
* but there are certain cases, including single label hosts
* and potentially single label interfaces for which the
* treatment can not be known in advance.
*
* The possibility of additional labeling schemes being
* introduced in the future exists as well.
*/
#define SMACK_UNLABELED_SOCKET 0
#define SMACK_CIPSO_SOCKET 1
/*
* smackfs magic number
*/
#define SMACK_MAGIC 0x43415d53 /* "SMAC" */
/*
* CIPSO defaults.
*/
#define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */
#define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */
#define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */
#define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */
#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */
#define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */
/*
* Flag for transmute access
*/
#define MAY_TRANSMUTE 64
/*
* Just to make the common cases easier to deal with
*/
#define MAY_ANYREAD (MAY_READ | MAY_EXEC)
#define MAY_READWRITE (MAY_READ | MAY_WRITE)
#define MAY_NOT 0
/*
* Number of access types used by Smack (rwxat)
*/
#define SMK_NUM_ACCESS_TYPE 5
/* SMACK data */
struct smack_audit_data {
const char *function;
char *subject;
char *object;
char *request;
int result;
};
/*
* Smack audit data; is empty if CONFIG_AUDIT not set
* to save some stack
*/
struct smk_audit_info {
#ifdef CONFIG_AUDIT
struct common_audit_data a;
struct smack_audit_data sad;
#endif
};
/*
* These functions are in smack_lsm.c
*/
struct inode_smack *new_inode_smack(char *);
/*
* These functions are in smack_access.c
*/
int smk_access_entry(char *, char *, struct list_head *);
int smk_access(char *, char *, int, 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);
void smk_parse_smack(const char *string, int len, char *smack);
char *smk_import(const char *, int);
struct smack_known *smk_import_entry(const char *, int);
struct smack_known *smk_find_entry(const char *);
u32 smack_to_secid(const char *);
/*
* Shared data.
*/
extern int smack_cipso_direct;
extern char *smack_net_ambient;
extern char *smack_onlycap;
extern const char *smack_cipso_option;
extern struct smack_known smack_known_floor;
extern struct smack_known smack_known_hat;
extern struct smack_known smack_known_huh;
extern struct smack_known smack_known_invalid;
extern struct smack_known smack_known_star;
extern struct smack_known smack_known_web;
extern struct list_head smack_known_list;
extern struct list_head smk_netlbladdr_list;
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?
*/
static inline int smk_inode_transmutable(const struct inode *isp)
{
struct inode_smack *sip = isp->i_security;
return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0;
}
/*
* Present a pointer to the smack label in an inode blob.
*/
static inline char *smk_of_inode(const struct inode *isp)
{
struct inode_smack *sip = isp->i_security;
return sip->smk_inode;
}
/*
* Present a pointer to the smack label in an task blob.
*/
static inline char *smk_of_task(const struct task_smack *tsp)
{
return tsp->smk_task;
}
/*
* Present a pointer to the forked smack label in an task blob.
*/
static inline char *smk_of_forked(const struct task_smack *tsp)
{
return tsp->smk_forked;
}
/*
* Present a pointer to the smack label in the current task blob.
*/
static inline char *smk_of_current(void)
{
return smk_of_task(current_security());
}
/*
* logging functions
*/
#define SMACK_AUDIT_DENIED 0x1
#define SMACK_AUDIT_ACCEPT 0x2
extern int log_policy;
void smack_log(char *subject_label, char *object_label,
int request,
int result, struct smk_audit_info *auditdata);
#ifdef CONFIG_AUDIT
/*
* some inline functions to set up audit data
* they do nothing if CONFIG_AUDIT is not set
*
*/
static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
char type)
{
memset(a, 0, sizeof(*a));
a->a.type = type;
a->a.smack_audit_data = &a->sad;
a->a.smack_audit_data->function = func;
}
static inline void smk_ad_init_net(struct smk_audit_info *a, const char *func,
char type, struct lsm_network_audit *net)
{
smk_ad_init(a, func, type);
memset(net, 0, sizeof(*net));
a->a.u.net = net;
}
static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
struct task_struct *t)
{
a->a.u.tsk = t;
}
static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a,
struct dentry *d)
{
a->a.u.dentry = d;
}
static inline void smk_ad_setfield_u_fs_inode(struct smk_audit_info *a,
struct inode *i)
{
a->a.u.inode = i;
}
static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a,
struct path p)
{
a->a.u.path = p;
}
static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
struct sock *sk)
{
a->a.u.net->sk = sk;
}
#else /* no AUDIT */
static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
char type)
{
}
static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
struct task_struct *t)
{
}
static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a,
struct dentry *d)
{
}
static inline void smk_ad_setfield_u_fs_path_mnt(struct smk_audit_info *a,
struct vfsmount *m)
{
}
static inline void smk_ad_setfield_u_fs_inode(struct smk_audit_info *a,
struct inode *i)
{
}
static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a,
struct path p)
{
}
static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
struct sock *sk)
{
}
#endif
#endif /* _SECURITY_SMACK_H */
+557
View File
@@ -0,0 +1,557 @@
/*
* Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* Author:
* Casey Schaufler <casey@schaufler-ca.com>
*
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include "smack.h"
struct smack_known smack_known_huh = {
.smk_known = "?",
.smk_secid = 2,
.smk_cipso = NULL,
};
struct smack_known smack_known_hat = {
.smk_known = "^",
.smk_secid = 3,
.smk_cipso = NULL,
};
struct smack_known smack_known_star = {
.smk_known = "*",
.smk_secid = 4,
.smk_cipso = NULL,
};
struct smack_known smack_known_floor = {
.smk_known = "_",
.smk_secid = 5,
.smk_cipso = NULL,
};
struct smack_known smack_known_invalid = {
.smk_known = "",
.smk_secid = 6,
.smk_cipso = NULL,
};
struct smack_known smack_known_web = {
.smk_known = "@",
.smk_secid = 7,
.smk_cipso = NULL,
};
LIST_HEAD(smack_known_list);
/*
* The initial value needs to be bigger than any of the
* known values above.
*/
static u32 smack_next_secid = 10;
/*
* what events do we log
* can be overwritten at run-time by /smack/logging
*/
int log_policy = SMACK_AUDIT_DENIED;
/**
* smk_access_entry - look up matching access rule
* @subject_label: a pointer to the subject's Smack label
* @object_label: a pointer to the object's Smack label
* @rule_list: the list of rules to search
*
* This function looks up the subject/object pair in the
* access rule list and returns the access mode. If no
* entry is found returns -ENOENT.
*
* NOTE:
*
* Earlier versions of this function allowed for labels that
* were not on the label list. This was done to allow for
* labels to come over the network that had never been seen
* before on this host. Unless the receiving socket has the
* star label this will always result in a failure check. The
* star labeled socket case is now handled in the networking
* hooks so there is no case where the label is not on the
* label list. Checking to see if the address of two labels
* is the same is now a reliable test.
*
* Do the object check first because that is more
* likely to differ.
*/
int smk_access_entry(char *subject_label, char *object_label,
struct list_head *rule_list)
{
int may = -ENOENT;
struct smack_rule *srp;
list_for_each_entry_rcu(srp, rule_list, list) {
if (srp->smk_object == object_label &&
srp->smk_subject == subject_label) {
may = srp->smk_access;
break;
}
}
return may;
}
/**
* smk_access - determine if a subject has a specific access to an object
* @subject_label: a pointer to the subject's Smack label
* @object_label: a pointer to the object's Smack label
* @request: the access requested, in "MAY" format
* @a : a pointer to the audit data
*
* This function looks up the subject/object pair in the
* access rule list and returns 0 if the access is permitted,
* non zero otherwise.
*
* Smack labels are shared on smack_list
*/
int smk_access(char *subject_label, char *object_label, int request,
struct smk_audit_info *a)
{
struct smack_known *skp;
int may = MAY_NOT;
int rc = 0;
/*
* Hardcoded comparisons.
*
* A star subject can't access any object.
*/
if (subject_label == smack_known_star.smk_known) {
rc = -EACCES;
goto out_audit;
}
/*
* An internet object can be accessed by any subject.
* Tasks cannot be assigned the internet label.
* An internet subject can access any object.
*/
if (object_label == smack_known_web.smk_known ||
subject_label == smack_known_web.smk_known)
goto out_audit;
/*
* A star object can be accessed by any subject.
*/
if (object_label == smack_known_star.smk_known)
goto out_audit;
/*
* An object can be accessed in any way by a subject
* with the same label.
*/
if (subject_label == object_label)
goto out_audit;
/*
* A hat subject can read any object.
* A floor object can be read by any subject.
*/
if ((request & MAY_ANYREAD) == request) {
if (object_label == smack_known_floor.smk_known)
goto out_audit;
if (subject_label == smack_known_hat.smk_known)
goto out_audit;
}
/*
* Beyond here an explicit relationship is required.
* If the requested access is contained in the available
* access (e.g. read is included in readwrite) it's
* good. A negative response from smk_access_entry()
* indicates there is no entry for this pair.
*/
skp = smk_find_entry(subject_label);
rcu_read_lock();
may = smk_access_entry(subject_label, object_label, &skp->smk_rules);
rcu_read_unlock();
if (may > 0 && (request & may) == request)
goto out_audit;
rc = -EACCES;
out_audit:
#ifdef CONFIG_AUDIT
if (a)
smack_log(subject_label, object_label, request, rc, a);
#endif
return rc;
}
/**
* smk_curacc - determine if current has a specific access to an object
* @obj_label: a pointer to the object's Smack label
* @mode: the access requested, in "MAY" format
* @a : common audit data
*
* This function checks the current subject label/object label pair
* in the access rule list and returns 0 if the access is permitted,
* non zero otherwise. It allows that current may have the capability
* to override the rules.
*/
int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
{
struct task_smack *tsp = current_security();
char *sp = smk_of_task(tsp);
int may;
int rc;
/*
* Check the global rule list
*/
rc = smk_access(sp, obj_label, mode, NULL);
if (rc == 0) {
/*
* If there is an entry in the task's rule list
* it can further restrict access.
*/
may = smk_access_entry(sp, obj_label, &tsp->smk_rules);
if (may < 0)
goto out_audit;
if ((mode & may) == mode)
goto out_audit;
rc = -EACCES;
}
/*
* Return if a specific label has been designated as the
* only one that gets privilege and current does not
* have that label.
*/
if (smack_onlycap != NULL && smack_onlycap != sp)
goto out_audit;
if (capable(CAP_MAC_OVERRIDE))
rc = 0;
out_audit:
#ifdef CONFIG_AUDIT
if (a)
smack_log(sp, obj_label, mode, rc, a);
#endif
return rc;
}
#ifdef CONFIG_AUDIT
/**
* smack_str_from_perm : helper to transalate an int to a
* readable string
* @string : the string to fill
* @access : the int
*
*/
static inline void smack_str_from_perm(char *string, int access)
{
int i = 0;
if (access & MAY_READ)
string[i++] = 'r';
if (access & MAY_WRITE)
string[i++] = 'w';
if (access & MAY_EXEC)
string[i++] = 'x';
if (access & MAY_APPEND)
string[i++] = 'a';
string[i] = '\0';
}
/**
* smack_log_callback - SMACK specific information
* will be called by generic audit code
* @ab : the audit_buffer
* @a : audit_data
*
*/
static void smack_log_callback(struct audit_buffer *ab, void *a)
{
struct common_audit_data *ad = a;
struct smack_audit_data *sad = ad->smack_audit_data;
audit_log_format(ab, "lsm=SMACK fn=%s action=%s",
ad->smack_audit_data->function,
sad->result ? "denied" : "granted");
audit_log_format(ab, " subject=");
audit_log_untrustedstring(ab, sad->subject);
audit_log_format(ab, " object=");
audit_log_untrustedstring(ab, sad->object);
audit_log_format(ab, " requested=%s", sad->request);
}
/**
* smack_log - Audit the granting or denial of permissions.
* @subject_label : smack label of the requester
* @object_label : smack label of the object being accessed
* @request: requested permissions
* @result: result from smk_access
* @a: auxiliary audit data
*
* Audit the granting or denial of permissions in accordance
* with the policy.
*/
void smack_log(char *subject_label, char *object_label, int request,
int result, struct smk_audit_info *ad)
{
char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
struct smack_audit_data *sad;
struct common_audit_data *a = &ad->a;
/* check if we have to log the current event */
if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
return;
if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
return;
sad = a->smack_audit_data;
if (sad->function == NULL)
sad->function = "unknown";
/* end preparing the audit data */
smack_str_from_perm(request_buffer, request);
sad->subject = subject_label;
sad->object = object_label;
sad->request = request_buffer;
sad->result = result;
common_lsm_audit(a, smack_log_callback, NULL);
}
#else /* #ifdef CONFIG_AUDIT */
void smack_log(char *subject_label, char *object_label, int request,
int result, struct smk_audit_info *ad)
{
}
#endif
static DEFINE_MUTEX(smack_known_lock);
/**
* smk_find_entry - find a label on the list, return the list entry
* @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.
*/
struct smack_known *smk_find_entry(const char *string)
{
struct smack_known *skp;
list_for_each_entry_rcu(skp, &smack_known_list, list) {
if (strncmp(skp->smk_known, string, SMK_MAXLEN) == 0)
return skp;
}
return NULL;
}
/**
* smk_parse_smack - parse smack label from a text string
* @string: a text string that might contain a Smack label
* @len: the maximum size, or zero if it is NULL terminated.
* @smack: parsed smack label, or NULL if parse error
*/
void smk_parse_smack(const char *string, int len, char *smack)
{
int found;
int i;
if (len <= 0 || len > SMK_MAXLEN)
len = SMK_MAXLEN;
for (i = 0, found = 0; i < SMK_LABELLEN; i++) {
if (found)
smack[i] = '\0';
else if (i >= len || string[i] > '~' || string[i] <= ' ' ||
string[i] == '/' || string[i] == '"' ||
string[i] == '\\' || string[i] == '\'') {
smack[i] = '\0';
found = 1;
} else
smack[i] = string[i];
}
}
/**
* smk_import_entry - import a label, return the list entry
* @string: a text string that might be a Smack label
* @len: the maximum size, or zero if it is NULL terminated.
*
* Returns a pointer to the entry in the label list that
* matches the passed string, adding it if necessary.
*/
struct smack_known *smk_import_entry(const char *string, int len)
{
struct smack_known *skp;
char smack[SMK_LABELLEN];
smk_parse_smack(string, len, smack);
if (smack[0] == '\0')
return NULL;
mutex_lock(&smack_known_lock);
skp = smk_find_entry(smack);
if (skp == NULL) {
skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
if (skp != NULL) {
strncpy(skp->smk_known, smack, SMK_MAXLEN);
skp->smk_secid = smack_next_secid++;
skp->smk_cipso = NULL;
INIT_LIST_HEAD(&skp->smk_rules);
spin_lock_init(&skp->smk_cipsolock);
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);
}
}
mutex_unlock(&smack_known_lock);
return skp;
}
/**
* smk_import - import a smack label
* @string: a text string that might be a Smack label
* @len: the maximum size, or zero if it is NULL terminated.
*
* Returns a pointer to the label in the label list that
* matches the passed string, adding it if necessary.
*/
char *smk_import(const char *string, int len)
{
struct smack_known *skp;
/* labels cannot begin with a '-' */
if (string[0] == '-')
return NULL;
skp = smk_import_entry(string, len);
if (skp == NULL)
return NULL;
return skp->smk_known;
}
/**
* smack_from_secid - find the Smack label associated with a secid
* @secid: an integer that might be associated with a Smack label
*
* Returns a pointer to the appropriate Smack label if there is one,
* otherwise a pointer to the invalid Smack label.
*/
char *smack_from_secid(const u32 secid)
{
struct smack_known *skp;
rcu_read_lock();
list_for_each_entry_rcu(skp, &smack_known_list, list) {
if (skp->smk_secid == secid) {
rcu_read_unlock();
return skp->smk_known;
}
}
/*
* If we got this far someone asked for the translation
* of a secid that is not on the list.
*/
rcu_read_unlock();
return smack_known_invalid.smk_known;
}
/**
* smack_to_secid - find the secid associated with a Smack label
* @smack: the Smack label
*
* Returns the appropriate secid if there is one,
* otherwise 0
*/
u32 smack_to_secid(const char *smack)
{
struct smack_known *skp;
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 (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;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff