Merge branch 'smack-for-4.3' of https://github.com/cschaufler/smack-next into next
This commit is contained in:
@@ -28,6 +28,10 @@ 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.
|
||||||
|
|
||||||
|
Smack is used in the Tizen operating system. Please
|
||||||
|
go to http://wiki.tizen.org for information about how
|
||||||
|
Smack is used in Tizen.
|
||||||
|
|
||||||
The current git repository for Smack user space is:
|
The current git repository for Smack user space is:
|
||||||
|
|
||||||
git://github.com/smack-team/smack.git
|
git://github.com/smack-team/smack.git
|
||||||
@@ -108,6 +112,8 @@ in the smackfs filesystem. This pseudo-filesystem is mounted
|
|||||||
on /sys/fs/smackfs.
|
on /sys/fs/smackfs.
|
||||||
|
|
||||||
access
|
access
|
||||||
|
Provided for backward compatibility. The access2 interface
|
||||||
|
is preferred and should be used instead.
|
||||||
This interface reports whether a subject with the specified
|
This interface reports whether a subject with the specified
|
||||||
Smack label has a particular access to an object with a
|
Smack label has a particular access to an object with a
|
||||||
specified Smack label. Write a fixed format access rule to
|
specified Smack label. Write a fixed format access rule to
|
||||||
@@ -136,6 +142,8 @@ change-rule
|
|||||||
those in the fourth string. If there is no such rule it will be
|
those in the fourth string. If there is no such rule it will be
|
||||||
created using the access specified in the third and the fourth strings.
|
created using the access specified in the third and the fourth strings.
|
||||||
cipso
|
cipso
|
||||||
|
Provided for backward compatibility. The cipso2 interface
|
||||||
|
is preferred and should be used instead.
|
||||||
This interface allows a specific CIPSO header to be assigned
|
This interface allows a specific CIPSO header to be assigned
|
||||||
to a Smack label. The format accepted on write is:
|
to a Smack label. The format accepted on write is:
|
||||||
"%24s%4d%4d"["%4d"]...
|
"%24s%4d%4d"["%4d"]...
|
||||||
@@ -157,7 +165,19 @@ direct
|
|||||||
doi
|
doi
|
||||||
This contains the CIPSO domain of interpretation used in
|
This contains the CIPSO domain of interpretation used in
|
||||||
network packets.
|
network packets.
|
||||||
|
ipv6host
|
||||||
|
This interface allows specific IPv6 internet addresses to be
|
||||||
|
treated as single label hosts. Packets are sent to single
|
||||||
|
label hosts 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:
|
||||||
|
"%h:%h:%h:%h:%h:%h:%h:%h label" or
|
||||||
|
"%h:%h:%h:%h:%h:%h:%h:%h/%d label".
|
||||||
|
The "::" address shortcut is not supported.
|
||||||
|
If label is "-DELETE" a matched entry will be deleted.
|
||||||
load
|
load
|
||||||
|
Provided for backward compatibility. The load2 interface
|
||||||
|
is preferred and should be used instead.
|
||||||
This interface allows access control rules in addition to
|
This interface allows access control rules in addition to
|
||||||
the system defined rules to be specified. The format accepted
|
the system defined rules to be specified. The format accepted
|
||||||
on write is:
|
on write is:
|
||||||
@@ -181,6 +201,8 @@ load2
|
|||||||
permissions that are not allowed. The string "r-x--" would
|
permissions that are not allowed. The string "r-x--" would
|
||||||
specify read and execute access.
|
specify read and execute access.
|
||||||
load-self
|
load-self
|
||||||
|
Provided for backward compatibility. The load-self2 interface
|
||||||
|
is preferred and should be used instead.
|
||||||
This interface allows process specific access rules to be
|
This interface allows process specific access rules to be
|
||||||
defined. These rules are only consulted if access would
|
defined. These rules are only consulted if access would
|
||||||
otherwise be permitted, and are intended to provide additional
|
otherwise be permitted, and are intended to provide additional
|
||||||
@@ -205,6 +227,8 @@ netlabel
|
|||||||
received from single label hosts are given the specified
|
received from single label hosts are given the specified
|
||||||
label. The format accepted on write is:
|
label. The format accepted on write is:
|
||||||
"%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label".
|
"%d.%d.%d.%d label" or "%d.%d.%d.%d/%d label".
|
||||||
|
If the label specified is "-CIPSO" the address is treated
|
||||||
|
as a host that supports CIPSO headers.
|
||||||
onlycap
|
onlycap
|
||||||
This contains labels 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
|
and CAP_MAC_OVERRIDE to be effective. If this file is empty
|
||||||
@@ -232,7 +256,8 @@ unconfined
|
|||||||
is dangerous and can ruin the proper labeling of your system.
|
is dangerous and can ruin the proper labeling of your system.
|
||||||
It should never be used in production.
|
It should never be used in production.
|
||||||
|
|
||||||
You can add access rules in /etc/smack/accesses. They take the form:
|
If you are using the smackload utility
|
||||||
|
you can add access rules in /etc/smack/accesses. They take the form:
|
||||||
|
|
||||||
subjectlabel objectlabel access
|
subjectlabel objectlabel access
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,26 @@
|
|||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/lsm_hooks.h>
|
#include <linux/lsm_hooks.h>
|
||||||
#include <linux/in.h>
|
#include <linux/in.h>
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
#include <linux/in6.h>
|
||||||
|
#endif /* CONFIG_IPV6 */
|
||||||
#include <net/netlabel.h>
|
#include <net/netlabel.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/rculist.h>
|
#include <linux/rculist.h>
|
||||||
#include <linux/lsm_audit.h>
|
#include <linux/lsm_audit.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use IPv6 port labeling if IPv6 is enabled and secmarks
|
||||||
|
* are not being used.
|
||||||
|
*/
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
|
||||||
|
#define SMACK_IPV6_PORT_LABELING 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6) && defined(CONFIG_SECURITY_SMACK_NETFILTER)
|
||||||
|
#define SMACK_IPV6_SECMARK_LABELING 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Smack labels were limited to 23 characters for a long time.
|
* Smack labels were limited to 23 characters for a long time.
|
||||||
*/
|
*/
|
||||||
@@ -118,15 +133,30 @@ struct smack_rule {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* An entry in the table identifying hosts.
|
* An entry in the table identifying IPv4 hosts.
|
||||||
*/
|
*/
|
||||||
struct smk_netlbladdr {
|
struct smk_net4addr {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct sockaddr_in smk_host; /* network address */
|
struct in_addr smk_host; /* network address */
|
||||||
struct in_addr smk_mask; /* network mask */
|
struct in_addr smk_mask; /* network mask */
|
||||||
|
int smk_masks; /* mask size */
|
||||||
struct smack_known *smk_label; /* label */
|
struct smack_known *smk_label; /* label */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
/*
|
||||||
|
* An entry in the table identifying IPv6 hosts.
|
||||||
|
*/
|
||||||
|
struct smk_net6addr {
|
||||||
|
struct list_head list;
|
||||||
|
struct in6_addr smk_host; /* network address */
|
||||||
|
struct in6_addr smk_mask; /* network mask */
|
||||||
|
int smk_masks; /* mask size */
|
||||||
|
struct smack_known *smk_label; /* label */
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_IPV6 */
|
||||||
|
|
||||||
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
/*
|
/*
|
||||||
* An entry in the table identifying ports.
|
* An entry in the table identifying ports.
|
||||||
*/
|
*/
|
||||||
@@ -137,12 +167,31 @@ struct smk_port_label {
|
|||||||
struct smack_known *smk_in; /* inbound label */
|
struct smack_known *smk_in; /* inbound label */
|
||||||
struct smack_known *smk_out; /* outgoing label */
|
struct smack_known *smk_out; /* outgoing label */
|
||||||
};
|
};
|
||||||
|
#endif /* SMACK_IPV6_PORT_LABELING */
|
||||||
|
|
||||||
struct smack_onlycap {
|
struct smack_onlycap {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct smack_known *smk_label;
|
struct smack_known *smk_label;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Super block security struct flags for mount options */
|
||||||
|
#define FSDEFAULT_MNT 0x01
|
||||||
|
#define FSFLOOR_MNT 0x02
|
||||||
|
#define FSHAT_MNT 0x04
|
||||||
|
#define FSROOT_MNT 0x08
|
||||||
|
#define FSTRANS_MNT 0x10
|
||||||
|
|
||||||
|
#define NUM_SMK_MNT_OPTS 5
|
||||||
|
|
||||||
|
enum {
|
||||||
|
Opt_error = -1,
|
||||||
|
Opt_fsdefault = 1,
|
||||||
|
Opt_fsfloor = 2,
|
||||||
|
Opt_fshat = 3,
|
||||||
|
Opt_fsroot = 4,
|
||||||
|
Opt_fstransmute = 5,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mount options
|
* Mount options
|
||||||
*/
|
*/
|
||||||
@@ -152,6 +201,7 @@ struct smack_onlycap {
|
|||||||
#define SMK_FSROOT "smackfsroot="
|
#define SMK_FSROOT "smackfsroot="
|
||||||
#define SMK_FSTRANS "smackfstransmute="
|
#define SMK_FSTRANS "smackfstransmute="
|
||||||
|
|
||||||
|
#define SMACK_DELETE_OPTION "-DELETE"
|
||||||
#define SMACK_CIPSO_OPTION "-CIPSO"
|
#define SMACK_CIPSO_OPTION "-CIPSO"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -234,10 +284,6 @@ struct smk_audit_info {
|
|||||||
struct smack_audit_data sad;
|
struct smack_audit_data sad;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
* These functions are in smack_lsm.c
|
|
||||||
*/
|
|
||||||
struct inode_smack *new_inode_smack(struct smack_known *);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions are in smack_access.c
|
* These functions are in smack_access.c
|
||||||
@@ -267,7 +313,6 @@ extern struct smack_known *smack_syslog_label;
|
|||||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||||
extern struct smack_known *smack_unconfined;
|
extern struct smack_known *smack_unconfined;
|
||||||
#endif
|
#endif
|
||||||
extern struct smack_known smack_cipso_option;
|
|
||||||
extern int smack_ptrace_rule;
|
extern int smack_ptrace_rule;
|
||||||
|
|
||||||
extern struct smack_known smack_known_floor;
|
extern struct smack_known smack_known_floor;
|
||||||
@@ -279,7 +324,10 @@ extern struct smack_known smack_known_web;
|
|||||||
|
|
||||||
extern struct mutex smack_known_lock;
|
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_net4addr_list;
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
extern struct list_head smk_net6addr_list;
|
||||||
|
#endif /* CONFIG_IPV6 */
|
||||||
|
|
||||||
extern struct mutex smack_onlycap_lock;
|
extern struct mutex smack_onlycap_lock;
|
||||||
extern struct list_head smack_onlycap_list;
|
extern struct list_head smack_onlycap_list;
|
||||||
|
|||||||
@@ -639,6 +639,12 @@ int smack_privileged(int cap)
|
|||||||
struct smack_known *skp = smk_of_current();
|
struct smack_known *skp = smk_of_current();
|
||||||
struct smack_onlycap *sop;
|
struct smack_onlycap *sop;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All kernel tasks are privileged
|
||||||
|
*/
|
||||||
|
if (unlikely(current->flags & PF_KTHREAD))
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (!capable(cap))
|
if (!capable(cap))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include <linux/msg.h>
|
#include <linux/msg.h>
|
||||||
#include <linux/shm.h>
|
#include <linux/shm.h>
|
||||||
#include <linux/binfmts.h>
|
#include <linux/binfmts.h>
|
||||||
|
#include <linux/parser.h>
|
||||||
#include "smack.h"
|
#include "smack.h"
|
||||||
|
|
||||||
#define TRANS_TRUE "TRUE"
|
#define TRANS_TRUE "TRUE"
|
||||||
@@ -50,9 +51,9 @@
|
|||||||
#define SMK_RECEIVING 1
|
#define SMK_RECEIVING 1
|
||||||
#define SMK_SENDING 2
|
#define SMK_SENDING 2
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
LIST_HEAD(smk_ipv6_port_list);
|
LIST_HEAD(smk_ipv6_port_list);
|
||||||
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
|
#endif
|
||||||
static struct kmem_cache *smack_inode_cache;
|
static struct kmem_cache *smack_inode_cache;
|
||||||
int smack_enabled;
|
int smack_enabled;
|
||||||
|
|
||||||
@@ -64,6 +65,15 @@ static char *smk_bu_mess[] = {
|
|||||||
"Unconfined Object", /* SMACK_UNCONFINED_OBJECT */
|
"Unconfined Object", /* SMACK_UNCONFINED_OBJECT */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const match_table_t tokens = {
|
||||||
|
{Opt_fsdefault, SMK_FSDEFAULT "%s"},
|
||||||
|
{Opt_fsfloor, SMK_FSFLOOR "%s"},
|
||||||
|
{Opt_fshat, SMK_FSHAT "%s"},
|
||||||
|
{Opt_fsroot, SMK_FSROOT "%s"},
|
||||||
|
{Opt_fstransmute, SMK_FSTRANS "%s"},
|
||||||
|
{Opt_error, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
static void smk_bu_mode(int mode, char *s)
|
static void smk_bu_mode(int mode, char *s)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -281,7 +291,7 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
|
|||||||
*
|
*
|
||||||
* Returns the new blob or NULL if there's no memory available
|
* Returns the new blob or NULL if there's no memory available
|
||||||
*/
|
*/
|
||||||
struct inode_smack *new_inode_smack(struct smack_known *skp)
|
static struct inode_smack *new_inode_smack(struct smack_known *skp)
|
||||||
{
|
{
|
||||||
struct inode_smack *isp;
|
struct inode_smack *isp;
|
||||||
|
|
||||||
@@ -577,76 +587,193 @@ static int smack_sb_copy_data(char *orig, char *smackopts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_sb_kern_mount - Smack specific mount processing
|
* smack_parse_opts_str - parse Smack specific mount options
|
||||||
|
* @options: mount options string
|
||||||
|
* @opts: where to store converted mount opts
|
||||||
|
*
|
||||||
|
* Returns 0 on success or -ENOMEM on error.
|
||||||
|
*
|
||||||
|
* converts Smack specific mount options to generic security option format
|
||||||
|
*/
|
||||||
|
static int smack_parse_opts_str(char *options,
|
||||||
|
struct security_mnt_opts *opts)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
char *fsdefault = NULL, *fsfloor = NULL;
|
||||||
|
char *fshat = NULL, *fsroot = NULL, *fstransmute = NULL;
|
||||||
|
int rc = -ENOMEM, num_mnt_opts = 0;
|
||||||
|
|
||||||
|
opts->num_mnt_opts = 0;
|
||||||
|
|
||||||
|
if (!options)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while ((p = strsep(&options, ",")) != NULL) {
|
||||||
|
int token;
|
||||||
|
substring_t args[MAX_OPT_ARGS];
|
||||||
|
|
||||||
|
if (!*p)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
token = match_token(p, tokens, args);
|
||||||
|
|
||||||
|
switch (token) {
|
||||||
|
case Opt_fsdefault:
|
||||||
|
if (fsdefault)
|
||||||
|
goto out_opt_err;
|
||||||
|
fsdefault = match_strdup(&args[0]);
|
||||||
|
if (!fsdefault)
|
||||||
|
goto out_err;
|
||||||
|
break;
|
||||||
|
case Opt_fsfloor:
|
||||||
|
if (fsfloor)
|
||||||
|
goto out_opt_err;
|
||||||
|
fsfloor = match_strdup(&args[0]);
|
||||||
|
if (!fsfloor)
|
||||||
|
goto out_err;
|
||||||
|
break;
|
||||||
|
case Opt_fshat:
|
||||||
|
if (fshat)
|
||||||
|
goto out_opt_err;
|
||||||
|
fshat = match_strdup(&args[0]);
|
||||||
|
if (!fshat)
|
||||||
|
goto out_err;
|
||||||
|
break;
|
||||||
|
case Opt_fsroot:
|
||||||
|
if (fsroot)
|
||||||
|
goto out_opt_err;
|
||||||
|
fsroot = match_strdup(&args[0]);
|
||||||
|
if (!fsroot)
|
||||||
|
goto out_err;
|
||||||
|
break;
|
||||||
|
case Opt_fstransmute:
|
||||||
|
if (fstransmute)
|
||||||
|
goto out_opt_err;
|
||||||
|
fstransmute = match_strdup(&args[0]);
|
||||||
|
if (!fstransmute)
|
||||||
|
goto out_err;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rc = -EINVAL;
|
||||||
|
pr_warn("Smack: unknown mount option\n");
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opts->mnt_opts = kcalloc(NUM_SMK_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
|
||||||
|
if (!opts->mnt_opts)
|
||||||
|
goto out_err;
|
||||||
|
|
||||||
|
opts->mnt_opts_flags = kcalloc(NUM_SMK_MNT_OPTS, sizeof(int),
|
||||||
|
GFP_ATOMIC);
|
||||||
|
if (!opts->mnt_opts_flags) {
|
||||||
|
kfree(opts->mnt_opts);
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fsdefault) {
|
||||||
|
opts->mnt_opts[num_mnt_opts] = fsdefault;
|
||||||
|
opts->mnt_opts_flags[num_mnt_opts++] = FSDEFAULT_MNT;
|
||||||
|
}
|
||||||
|
if (fsfloor) {
|
||||||
|
opts->mnt_opts[num_mnt_opts] = fsfloor;
|
||||||
|
opts->mnt_opts_flags[num_mnt_opts++] = FSFLOOR_MNT;
|
||||||
|
}
|
||||||
|
if (fshat) {
|
||||||
|
opts->mnt_opts[num_mnt_opts] = fshat;
|
||||||
|
opts->mnt_opts_flags[num_mnt_opts++] = FSHAT_MNT;
|
||||||
|
}
|
||||||
|
if (fsroot) {
|
||||||
|
opts->mnt_opts[num_mnt_opts] = fsroot;
|
||||||
|
opts->mnt_opts_flags[num_mnt_opts++] = FSROOT_MNT;
|
||||||
|
}
|
||||||
|
if (fstransmute) {
|
||||||
|
opts->mnt_opts[num_mnt_opts] = fstransmute;
|
||||||
|
opts->mnt_opts_flags[num_mnt_opts++] = FSTRANS_MNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
opts->num_mnt_opts = num_mnt_opts;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_opt_err:
|
||||||
|
rc = -EINVAL;
|
||||||
|
pr_warn("Smack: duplicate mount options\n");
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
kfree(fsdefault);
|
||||||
|
kfree(fsfloor);
|
||||||
|
kfree(fshat);
|
||||||
|
kfree(fsroot);
|
||||||
|
kfree(fstransmute);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smack_set_mnt_opts - set Smack specific mount options
|
||||||
* @sb: the file system superblock
|
* @sb: the file system superblock
|
||||||
* @flags: the mount flags
|
* @opts: Smack mount options
|
||||||
* @data: the smack mount options
|
* @kern_flags: mount option from kernel space or user space
|
||||||
|
* @set_kern_flags: where to store converted mount opts
|
||||||
*
|
*
|
||||||
* Returns 0 on success, an error code on failure
|
* Returns 0 on success, an error code on failure
|
||||||
|
*
|
||||||
|
* Allow filesystems with binary mount data to explicitly set Smack mount
|
||||||
|
* labels.
|
||||||
*/
|
*/
|
||||||
static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
|
static int smack_set_mnt_opts(struct super_block *sb,
|
||||||
|
struct security_mnt_opts *opts,
|
||||||
|
unsigned long kern_flags,
|
||||||
|
unsigned long *set_kern_flags)
|
||||||
{
|
{
|
||||||
struct dentry *root = sb->s_root;
|
struct dentry *root = sb->s_root;
|
||||||
struct inode *inode = d_backing_inode(root);
|
struct inode *inode = d_backing_inode(root);
|
||||||
struct superblock_smack *sp = sb->s_security;
|
struct superblock_smack *sp = sb->s_security;
|
||||||
struct inode_smack *isp;
|
struct inode_smack *isp;
|
||||||
struct smack_known *skp;
|
struct smack_known *skp;
|
||||||
char *op;
|
int i;
|
||||||
char *commap;
|
int num_opts = opts->num_mnt_opts;
|
||||||
int transmute = 0;
|
int transmute = 0;
|
||||||
int specified = 0;
|
|
||||||
|
|
||||||
if (sp->smk_initialized)
|
if (sp->smk_initialized)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sp->smk_initialized = 1;
|
sp->smk_initialized = 1;
|
||||||
|
|
||||||
for (op = data; op != NULL; op = commap) {
|
for (i = 0; i < num_opts; i++) {
|
||||||
commap = strchr(op, ',');
|
switch (opts->mnt_opts_flags[i]) {
|
||||||
if (commap != NULL)
|
case FSDEFAULT_MNT:
|
||||||
*commap++ = '\0';
|
skp = smk_import_entry(opts->mnt_opts[i], 0);
|
||||||
|
|
||||||
if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) {
|
|
||||||
op += strlen(SMK_FSHAT);
|
|
||||||
skp = smk_import_entry(op, 0);
|
|
||||||
if (IS_ERR(skp))
|
|
||||||
return PTR_ERR(skp);
|
|
||||||
sp->smk_hat = skp;
|
|
||||||
specified = 1;
|
|
||||||
|
|
||||||
} else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) {
|
|
||||||
op += strlen(SMK_FSFLOOR);
|
|
||||||
skp = smk_import_entry(op, 0);
|
|
||||||
if (IS_ERR(skp))
|
|
||||||
return PTR_ERR(skp);
|
|
||||||
sp->smk_floor = skp;
|
|
||||||
specified = 1;
|
|
||||||
|
|
||||||
} else if (strncmp(op, SMK_FSDEFAULT,
|
|
||||||
strlen(SMK_FSDEFAULT)) == 0) {
|
|
||||||
op += strlen(SMK_FSDEFAULT);
|
|
||||||
skp = smk_import_entry(op, 0);
|
|
||||||
if (IS_ERR(skp))
|
if (IS_ERR(skp))
|
||||||
return PTR_ERR(skp);
|
return PTR_ERR(skp);
|
||||||
sp->smk_default = skp;
|
sp->smk_default = skp;
|
||||||
specified = 1;
|
break;
|
||||||
|
case FSFLOOR_MNT:
|
||||||
} else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) {
|
skp = smk_import_entry(opts->mnt_opts[i], 0);
|
||||||
op += strlen(SMK_FSROOT);
|
if (IS_ERR(skp))
|
||||||
skp = smk_import_entry(op, 0);
|
return PTR_ERR(skp);
|
||||||
|
sp->smk_floor = skp;
|
||||||
|
break;
|
||||||
|
case FSHAT_MNT:
|
||||||
|
skp = smk_import_entry(opts->mnt_opts[i], 0);
|
||||||
|
if (IS_ERR(skp))
|
||||||
|
return PTR_ERR(skp);
|
||||||
|
sp->smk_hat = skp;
|
||||||
|
break;
|
||||||
|
case FSROOT_MNT:
|
||||||
|
skp = smk_import_entry(opts->mnt_opts[i], 0);
|
||||||
if (IS_ERR(skp))
|
if (IS_ERR(skp))
|
||||||
return PTR_ERR(skp);
|
return PTR_ERR(skp);
|
||||||
sp->smk_root = skp;
|
sp->smk_root = skp;
|
||||||
specified = 1;
|
break;
|
||||||
|
case FSTRANS_MNT:
|
||||||
} else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) {
|
skp = smk_import_entry(opts->mnt_opts[i], 0);
|
||||||
op += strlen(SMK_FSTRANS);
|
|
||||||
skp = smk_import_entry(op, 0);
|
|
||||||
if (IS_ERR(skp))
|
if (IS_ERR(skp))
|
||||||
return PTR_ERR(skp);
|
return PTR_ERR(skp);
|
||||||
sp->smk_root = skp;
|
sp->smk_root = skp;
|
||||||
transmute = 1;
|
transmute = 1;
|
||||||
specified = 1;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,7 +781,7 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
|
|||||||
/*
|
/*
|
||||||
* Unprivileged mounts don't get to specify Smack values.
|
* Unprivileged mounts don't get to specify Smack values.
|
||||||
*/
|
*/
|
||||||
if (specified)
|
if (num_opts)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
/*
|
/*
|
||||||
* Unprivileged mounts get root and default from the caller.
|
* Unprivileged mounts get root and default from the caller.
|
||||||
@@ -663,6 +790,7 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
|
|||||||
sp->smk_root = skp;
|
sp->smk_root = skp;
|
||||||
sp->smk_default = skp;
|
sp->smk_default = skp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the root inode.
|
* Initialize the root inode.
|
||||||
*/
|
*/
|
||||||
@@ -681,6 +809,37 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smack_sb_kern_mount - Smack specific mount processing
|
||||||
|
* @sb: the file system superblock
|
||||||
|
* @flags: the mount flags
|
||||||
|
* @data: the smack mount options
|
||||||
|
*
|
||||||
|
* Returns 0 on success, an error code on failure
|
||||||
|
*/
|
||||||
|
static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
char *options = data;
|
||||||
|
struct security_mnt_opts opts;
|
||||||
|
|
||||||
|
security_init_mnt_opts(&opts);
|
||||||
|
|
||||||
|
if (!options)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
rc = smack_parse_opts_str(options, &opts);
|
||||||
|
if (rc)
|
||||||
|
goto out_err;
|
||||||
|
|
||||||
|
out:
|
||||||
|
rc = smack_set_mnt_opts(sb, &opts, 0, NULL);
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
security_free_mnt_opts(&opts);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_sb_statfs - Smack check on statfs
|
* smack_sb_statfs - Smack check on statfs
|
||||||
* @dentry: identifies the file system in question
|
* @dentry: identifies the file system in question
|
||||||
@@ -2113,7 +2272,7 @@ static void smack_sk_free_security(struct sock *sk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_host_label - check host based restrictions
|
* smack_ipv4host_label - check host based restrictions
|
||||||
* @sip: the object end
|
* @sip: the object end
|
||||||
*
|
*
|
||||||
* looks for host based access restrictions
|
* looks for host based access restrictions
|
||||||
@@ -2124,30 +2283,96 @@ static void smack_sk_free_security(struct sock *sk)
|
|||||||
*
|
*
|
||||||
* Returns the label of the far end or NULL if it's not special.
|
* Returns the label of the far end or NULL if it's not special.
|
||||||
*/
|
*/
|
||||||
static struct smack_known *smack_host_label(struct sockaddr_in *sip)
|
static struct smack_known *smack_ipv4host_label(struct sockaddr_in *sip)
|
||||||
{
|
{
|
||||||
struct smk_netlbladdr *snp;
|
struct smk_net4addr *snp;
|
||||||
struct in_addr *siap = &sip->sin_addr;
|
struct in_addr *siap = &sip->sin_addr;
|
||||||
|
|
||||||
if (siap->s_addr == 0)
|
if (siap->s_addr == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list)
|
list_for_each_entry_rcu(snp, &smk_net4addr_list, list)
|
||||||
/*
|
/*
|
||||||
* we break after finding the first match because
|
* we break after finding the first match because
|
||||||
* the list is sorted from longest to shortest mask
|
* the list is sorted from longest to shortest mask
|
||||||
* so we have found the most specific match
|
* so we have found the most specific match
|
||||||
*/
|
*/
|
||||||
if ((&snp->smk_host.sin_addr)->s_addr ==
|
if (snp->smk_host.s_addr ==
|
||||||
(siap->s_addr & (&snp->smk_mask)->s_addr)) {
|
(siap->s_addr & snp->smk_mask.s_addr))
|
||||||
/* we have found the special CIPSO option */
|
return snp->smk_label;
|
||||||
if (snp->smk_label == &smack_cipso_option)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
/*
|
||||||
|
* smk_ipv6_localhost - Check for local ipv6 host address
|
||||||
|
* @sip: the address
|
||||||
|
*
|
||||||
|
* Returns boolean true if this is the localhost address
|
||||||
|
*/
|
||||||
|
static bool smk_ipv6_localhost(struct sockaddr_in6 *sip)
|
||||||
|
{
|
||||||
|
__be16 *be16p = (__be16 *)&sip->sin6_addr;
|
||||||
|
__be32 *be32p = (__be32 *)&sip->sin6_addr;
|
||||||
|
|
||||||
|
if (be32p[0] == 0 && be32p[1] == 0 && be32p[2] == 0 && be16p[6] == 0 &&
|
||||||
|
ntohs(be16p[7]) == 1)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smack_ipv6host_label - check host based restrictions
|
||||||
|
* @sip: the object end
|
||||||
|
*
|
||||||
|
* looks for host based access restrictions
|
||||||
|
*
|
||||||
|
* This version will only be appropriate for really small sets of single label
|
||||||
|
* hosts. The caller is responsible for ensuring that the RCU read lock is
|
||||||
|
* taken before calling this function.
|
||||||
|
*
|
||||||
|
* Returns the label of the far end or NULL if it's not special.
|
||||||
|
*/
|
||||||
|
static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip)
|
||||||
|
{
|
||||||
|
struct smk_net6addr *snp;
|
||||||
|
struct in6_addr *sap = &sip->sin6_addr;
|
||||||
|
int i;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It's local. Don't look for a host label.
|
||||||
|
*/
|
||||||
|
if (smk_ipv6_localhost(sip))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
list_for_each_entry_rcu(snp, &smk_net6addr_list, list) {
|
||||||
|
/*
|
||||||
|
* we break after finding the first match because
|
||||||
|
* the list is sorted from longest to shortest mask
|
||||||
|
* so we have found the most specific match
|
||||||
|
*/
|
||||||
|
for (found = 1, i = 0; i < 8; i++) {
|
||||||
|
/*
|
||||||
|
* If the label is NULL the entry has
|
||||||
|
* been renounced. Ignore it.
|
||||||
|
*/
|
||||||
|
if (snp->smk_label == NULL)
|
||||||
|
continue;
|
||||||
|
if ((sap->s6_addr16[i] & snp->smk_mask.s6_addr16[i]) !=
|
||||||
|
snp->smk_host.s6_addr16[i]) {
|
||||||
|
found = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found)
|
||||||
return snp->smk_label;
|
return snp->smk_label;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_IPV6 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_netlabel - Set the secattr on a socket
|
* smack_netlabel - Set the secattr on a socket
|
||||||
@@ -2211,7 +2436,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
|
|||||||
struct smk_audit_info ad;
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
hkp = smack_host_label(sap);
|
hkp = smack_ipv4host_label(sap);
|
||||||
if (hkp != NULL) {
|
if (hkp != NULL) {
|
||||||
#ifdef CONFIG_AUDIT
|
#ifdef CONFIG_AUDIT
|
||||||
struct lsm_network_audit net;
|
struct lsm_network_audit net;
|
||||||
@@ -2236,7 +2461,42 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
|
|||||||
return smack_netlabel(sk, sk_lbl);
|
return smack_netlabel(sk, sk_lbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
/**
|
||||||
|
* smk_ipv6_check - check Smack access
|
||||||
|
* @subject: subject Smack label
|
||||||
|
* @object: object Smack label
|
||||||
|
* @address: address
|
||||||
|
* @act: the action being taken
|
||||||
|
*
|
||||||
|
* Check an IPv6 access
|
||||||
|
*/
|
||||||
|
static int smk_ipv6_check(struct smack_known *subject,
|
||||||
|
struct smack_known *object,
|
||||||
|
struct sockaddr_in6 *address, int act)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
struct lsm_network_audit net;
|
||||||
|
#endif
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
|
||||||
|
ad.a.u.net->family = PF_INET6;
|
||||||
|
ad.a.u.net->dport = ntohs(address->sin6_port);
|
||||||
|
if (act == SMK_RECEIVING)
|
||||||
|
ad.a.u.net->v6info.saddr = address->sin6_addr;
|
||||||
|
else
|
||||||
|
ad.a.u.net->v6info.daddr = address->sin6_addr;
|
||||||
|
#endif
|
||||||
|
rc = smk_access(subject, object, MAY_WRITE, &ad);
|
||||||
|
rc = smk_bu_note("IPv6 check", subject, object, MAY_WRITE, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IPV6 */
|
||||||
|
|
||||||
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
/**
|
/**
|
||||||
* smk_ipv6_port_label - Smack port access table management
|
* smk_ipv6_port_label - Smack port access table management
|
||||||
* @sock: socket
|
* @sock: socket
|
||||||
@@ -2320,48 +2580,43 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
|
|||||||
static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
|
static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
|
||||||
int act)
|
int act)
|
||||||
{
|
{
|
||||||
__be16 *bep;
|
|
||||||
__be32 *be32p;
|
|
||||||
struct smk_port_label *spp;
|
struct smk_port_label *spp;
|
||||||
struct socket_smack *ssp = sk->sk_security;
|
struct socket_smack *ssp = sk->sk_security;
|
||||||
struct smack_known *skp;
|
struct smack_known *skp = NULL;
|
||||||
unsigned short port = 0;
|
unsigned short port;
|
||||||
struct smack_known *object;
|
struct smack_known *object;
|
||||||
struct smk_audit_info ad;
|
|
||||||
int rc;
|
|
||||||
#ifdef CONFIG_AUDIT
|
|
||||||
struct lsm_network_audit net;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (act == SMK_RECEIVING) {
|
if (act == SMK_RECEIVING) {
|
||||||
skp = smack_net_ambient;
|
skp = smack_ipv6host_label(address);
|
||||||
object = ssp->smk_in;
|
object = ssp->smk_in;
|
||||||
} else {
|
} else {
|
||||||
skp = ssp->smk_out;
|
skp = ssp->smk_out;
|
||||||
object = smack_net_ambient;
|
object = smack_ipv6host_label(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the IP address and port from the address.
|
* The other end is a single label host.
|
||||||
*/
|
*/
|
||||||
port = ntohs(address->sin6_port);
|
if (skp != NULL && object != NULL)
|
||||||
bep = (__be16 *)(&address->sin6_addr);
|
return smk_ipv6_check(skp, object, address, act);
|
||||||
be32p = (__be32 *)(&address->sin6_addr);
|
if (skp == NULL)
|
||||||
|
skp = smack_net_ambient;
|
||||||
|
if (object == NULL)
|
||||||
|
object = smack_net_ambient;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It's remote, so port lookup does no good.
|
* It's remote, so port lookup does no good.
|
||||||
*/
|
*/
|
||||||
if (be32p[0] || be32p[1] || be32p[2] || bep[6] || ntohs(bep[7]) != 1)
|
if (!smk_ipv6_localhost(address))
|
||||||
goto auditout;
|
return smk_ipv6_check(skp, object, address, act);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It's local so the send check has to have passed.
|
* It's local so the send check has to have passed.
|
||||||
*/
|
*/
|
||||||
if (act == SMK_RECEIVING) {
|
if (act == SMK_RECEIVING)
|
||||||
skp = &smack_known_web;
|
return 0;
|
||||||
goto auditout;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
port = ntohs(address->sin6_port);
|
||||||
list_for_each_entry(spp, &smk_ipv6_port_list, list) {
|
list_for_each_entry(spp, &smk_ipv6_port_list, list) {
|
||||||
if (spp->smk_port != port)
|
if (spp->smk_port != port)
|
||||||
continue;
|
continue;
|
||||||
@@ -2371,22 +2626,9 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auditout:
|
return smk_ipv6_check(skp, object, address, act);
|
||||||
|
|
||||||
#ifdef CONFIG_AUDIT
|
|
||||||
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
|
|
||||||
ad.a.u.net->family = sk->sk_family;
|
|
||||||
ad.a.u.net->dport = port;
|
|
||||||
if (act == SMK_RECEIVING)
|
|
||||||
ad.a.u.net->v6info.saddr = address->sin6_addr;
|
|
||||||
else
|
|
||||||
ad.a.u.net->v6info.daddr = address->sin6_addr;
|
|
||||||
#endif
|
|
||||||
rc = smk_access(skp, object, MAY_WRITE, &ad);
|
|
||||||
rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
|
#endif /* SMACK_IPV6_PORT_LABELING */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_inode_setsecurity - set smack xattrs
|
* smack_inode_setsecurity - set smack xattrs
|
||||||
@@ -2447,10 +2689,10 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
|
|||||||
} else
|
} else
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
if (sock->sk->sk_family == PF_INET6)
|
if (sock->sk->sk_family == PF_INET6)
|
||||||
smk_ipv6_port_label(sock, NULL);
|
smk_ipv6_port_label(sock, NULL);
|
||||||
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2492,7 +2734,7 @@ static int smack_socket_post_create(struct socket *sock, int family,
|
|||||||
return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
|
return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_SECURITY_SMACK_NETFILTER
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
/**
|
/**
|
||||||
* smack_socket_bind - record port binding information.
|
* smack_socket_bind - record port binding information.
|
||||||
* @sock: the socket
|
* @sock: the socket
|
||||||
@@ -2506,14 +2748,11 @@ static int smack_socket_post_create(struct socket *sock, int family,
|
|||||||
static int smack_socket_bind(struct socket *sock, struct sockaddr *address,
|
static int smack_socket_bind(struct socket *sock, struct sockaddr *address,
|
||||||
int addrlen)
|
int addrlen)
|
||||||
{
|
{
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
|
||||||
if (sock->sk != NULL && sock->sk->sk_family == PF_INET6)
|
if (sock->sk != NULL && sock->sk->sk_family == PF_INET6)
|
||||||
smk_ipv6_port_label(sock, address);
|
smk_ipv6_port_label(sock, address);
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* !CONFIG_SECURITY_SMACK_NETFILTER */
|
#endif /* SMACK_IPV6_PORT_LABELING */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_socket_connect - connect access check
|
* smack_socket_connect - connect access check
|
||||||
@@ -2529,6 +2768,13 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
|
|||||||
int addrlen)
|
int addrlen)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap;
|
||||||
|
#endif
|
||||||
|
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||||
|
struct smack_known *rsp;
|
||||||
|
struct socket_smack *ssp = sock->sk->sk_security;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (sock->sk == NULL)
|
if (sock->sk == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2542,10 +2788,15 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
|
|||||||
case PF_INET6:
|
case PF_INET6:
|
||||||
if (addrlen < sizeof(struct sockaddr_in6))
|
if (addrlen < sizeof(struct sockaddr_in6))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
|
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||||
rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap,
|
rsp = smack_ipv6host_label(sip);
|
||||||
|
if (rsp != NULL)
|
||||||
|
rc = smk_ipv6_check(ssp->smk_out, rsp, sip,
|
||||||
SMK_CONNECTING);
|
SMK_CONNECTING);
|
||||||
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
|
#endif
|
||||||
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
|
rc = smk_ipv6_port_check(sock->sk, sip, SMK_CONNECTING);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
@@ -3431,9 +3682,13 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
|
|||||||
int size)
|
int size)
|
||||||
{
|
{
|
||||||
struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
|
struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
|
||||||
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
|
struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
|
||||||
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
|
#endif
|
||||||
|
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||||
|
struct socket_smack *ssp = sock->sk->sk_security;
|
||||||
|
struct smack_known *rsp;
|
||||||
|
#endif
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3447,9 +3702,15 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
|
|||||||
rc = smack_netlabel_send(sock->sk, sip);
|
rc = smack_netlabel_send(sock->sk, sip);
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
|
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||||
|
rsp = smack_ipv6host_label(sap);
|
||||||
|
if (rsp != NULL)
|
||||||
|
rc = smk_ipv6_check(ssp->smk_out, rsp, sap,
|
||||||
|
SMK_CONNECTING);
|
||||||
|
#endif
|
||||||
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING);
|
rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING);
|
||||||
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
@@ -3663,10 +3924,12 @@ access_check:
|
|||||||
proto = smk_skb_to_addr_ipv6(skb, &sadd);
|
proto = smk_skb_to_addr_ipv6(skb, &sadd);
|
||||||
if (proto != IPPROTO_UDP && proto != IPPROTO_TCP)
|
if (proto != IPPROTO_UDP && proto != IPPROTO_TCP)
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
|
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||||
if (skb && skb->secmark != 0)
|
if (skb && skb->secmark != 0)
|
||||||
skp = smack_from_secid(skb->secmark);
|
skp = smack_from_secid(skb->secmark);
|
||||||
else
|
else
|
||||||
|
skp = smack_ipv6host_label(&sadd);
|
||||||
|
if (skp == NULL)
|
||||||
skp = smack_net_ambient;
|
skp = smack_net_ambient;
|
||||||
#ifdef CONFIG_AUDIT
|
#ifdef CONFIG_AUDIT
|
||||||
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
|
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
|
||||||
@@ -3677,9 +3940,10 @@ access_check:
|
|||||||
rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad);
|
rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad);
|
||||||
rc = smk_bu_note("IPv6 delivery", skp, ssp->smk_in,
|
rc = smk_bu_note("IPv6 delivery", skp, ssp->smk_in,
|
||||||
MAY_WRITE, rc);
|
MAY_WRITE, rc);
|
||||||
#else /* CONFIG_SECURITY_SMACK_NETFILTER */
|
#endif /* SMACK_IPV6_SECMARK_LABELING */
|
||||||
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING);
|
rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING);
|
||||||
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
|
#endif /* SMACK_IPV6_PORT_LABELING */
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_IPV6 */
|
#endif /* CONFIG_IPV6 */
|
||||||
}
|
}
|
||||||
@@ -3777,13 +4041,11 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
|
|||||||
}
|
}
|
||||||
netlbl_secattr_destroy(&secattr);
|
netlbl_secattr_destroy(&secattr);
|
||||||
break;
|
break;
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
|
||||||
case PF_INET6:
|
case PF_INET6:
|
||||||
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
|
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||||
s = skb->secmark;
|
s = skb->secmark;
|
||||||
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
|
#endif
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_IPV6 */
|
|
||||||
}
|
}
|
||||||
*secid = s;
|
*secid = s;
|
||||||
if (s == 0)
|
if (s == 0)
|
||||||
@@ -3906,7 +4168,7 @@ access_check:
|
|||||||
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();
|
||||||
hskp = smack_host_label(&addr);
|
hskp = smack_ipv4host_label(&addr);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (hskp == NULL)
|
if (hskp == NULL)
|
||||||
@@ -4254,7 +4516,7 @@ static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct security_hook_list smack_hooks[] = {
|
static struct security_hook_list smack_hooks[] = {
|
||||||
LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
|
LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
|
||||||
LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
|
LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
|
||||||
LSM_HOOK_INIT(syslog, smack_syslog),
|
LSM_HOOK_INIT(syslog, smack_syslog),
|
||||||
@@ -4264,6 +4526,8 @@ struct security_hook_list smack_hooks[] = {
|
|||||||
LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data),
|
LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data),
|
||||||
LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount),
|
LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount),
|
||||||
LSM_HOOK_INIT(sb_statfs, smack_sb_statfs),
|
LSM_HOOK_INIT(sb_statfs, smack_sb_statfs),
|
||||||
|
LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts),
|
||||||
|
LSM_HOOK_INIT(sb_parse_opts_str, smack_parse_opts_str),
|
||||||
|
|
||||||
LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds),
|
LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds),
|
||||||
LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds),
|
LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds),
|
||||||
@@ -4356,9 +4620,9 @@ struct security_hook_list smack_hooks[] = {
|
|||||||
LSM_HOOK_INIT(unix_may_send, smack_unix_may_send),
|
LSM_HOOK_INIT(unix_may_send, smack_unix_may_send),
|
||||||
|
|
||||||
LSM_HOOK_INIT(socket_post_create, smack_socket_post_create),
|
LSM_HOOK_INIT(socket_post_create, smack_socket_post_create),
|
||||||
#ifndef CONFIG_SECURITY_SMACK_NETFILTER
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
LSM_HOOK_INIT(socket_bind, smack_socket_bind),
|
LSM_HOOK_INIT(socket_bind, smack_socket_bind),
|
||||||
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
|
#endif
|
||||||
LSM_HOOK_INIT(socket_connect, smack_socket_connect),
|
LSM_HOOK_INIT(socket_connect, smack_socket_connect),
|
||||||
LSM_HOOK_INIT(socket_sendmsg, smack_socket_sendmsg),
|
LSM_HOOK_INIT(socket_sendmsg, smack_socket_sendmsg),
|
||||||
LSM_HOOK_INIT(socket_sock_rcv_skb, smack_socket_sock_rcv_skb),
|
LSM_HOOK_INIT(socket_sock_rcv_skb, smack_socket_sock_rcv_skb),
|
||||||
@@ -4453,7 +4717,16 @@ static __init int smack_init(void)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(KERN_INFO "Smack: Initializing.\n");
|
pr_info("Smack: Initializing.\n");
|
||||||
|
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
|
||||||
|
pr_info("Smack: Netfilter enabled.\n");
|
||||||
|
#endif
|
||||||
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
|
pr_info("Smack: IPv6 port labeling enabled.\n");
|
||||||
|
#endif
|
||||||
|
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||||
|
pr_info("Smack: IPv6 Netfilter enabled.\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the security state for the initial task.
|
* Set the security state for the initial task.
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <linux/magic.h>
|
#include <linux/magic.h>
|
||||||
#include "smack.h"
|
#include "smack.h"
|
||||||
|
|
||||||
|
#define BEBITS (sizeof(__be32) * 8)
|
||||||
/*
|
/*
|
||||||
* smackfs pseudo filesystem.
|
* smackfs pseudo filesystem.
|
||||||
*/
|
*/
|
||||||
@@ -40,7 +41,7 @@ enum smk_inos {
|
|||||||
SMK_DOI = 5, /* CIPSO DOI */
|
SMK_DOI = 5, /* CIPSO DOI */
|
||||||
SMK_DIRECT = 6, /* CIPSO level indicating direct label */
|
SMK_DIRECT = 6, /* CIPSO level indicating direct label */
|
||||||
SMK_AMBIENT = 7, /* internet ambient label */
|
SMK_AMBIENT = 7, /* internet ambient label */
|
||||||
SMK_NETLBLADDR = 8, /* single label hosts */
|
SMK_NET4ADDR = 8, /* single label hosts */
|
||||||
SMK_ONLYCAP = 9, /* the only "capable" label */
|
SMK_ONLYCAP = 9, /* the only "capable" label */
|
||||||
SMK_LOGGING = 10, /* logging */
|
SMK_LOGGING = 10, /* logging */
|
||||||
SMK_LOAD_SELF = 11, /* task specific rules */
|
SMK_LOAD_SELF = 11, /* task specific rules */
|
||||||
@@ -57,6 +58,9 @@ enum smk_inos {
|
|||||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||||
SMK_UNCONFINED = 22, /* define an unconfined label */
|
SMK_UNCONFINED = 22, /* define an unconfined label */
|
||||||
#endif
|
#endif
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
SMK_NET6ADDR = 23, /* single label IPv6 hosts */
|
||||||
|
#endif /* CONFIG_IPV6 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -64,7 +68,10 @@ enum smk_inos {
|
|||||||
*/
|
*/
|
||||||
static DEFINE_MUTEX(smack_cipso_lock);
|
static DEFINE_MUTEX(smack_cipso_lock);
|
||||||
static DEFINE_MUTEX(smack_ambient_lock);
|
static DEFINE_MUTEX(smack_ambient_lock);
|
||||||
static DEFINE_MUTEX(smk_netlbladdr_lock);
|
static DEFINE_MUTEX(smk_net4addr_lock);
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
static DEFINE_MUTEX(smk_net6addr_lock);
|
||||||
|
#endif /* CONFIG_IPV6 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the "ambient" label for network traffic.
|
* This is the "ambient" label for network traffic.
|
||||||
@@ -118,7 +125,10 @@ int smack_ptrace_rule = SMACK_PTRACE_DEFAULT;
|
|||||||
* can write to the specified label.
|
* can write to the specified label.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
LIST_HEAD(smk_netlbladdr_list);
|
LIST_HEAD(smk_net4addr_list);
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
LIST_HEAD(smk_net6addr_list);
|
||||||
|
#endif /* CONFIG_IPV6 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rule lists are maintained for each label.
|
* Rule lists are maintained for each label.
|
||||||
@@ -129,7 +139,7 @@ struct smack_master_list {
|
|||||||
struct smack_rule *smk_rule;
|
struct smack_rule *smk_rule;
|
||||||
};
|
};
|
||||||
|
|
||||||
LIST_HEAD(smack_rule_list);
|
static LIST_HEAD(smack_rule_list);
|
||||||
|
|
||||||
struct smack_parsed_rule {
|
struct smack_parsed_rule {
|
||||||
struct smack_known *smk_subject;
|
struct smack_known *smk_subject;
|
||||||
@@ -140,11 +150,6 @@ struct smack_parsed_rule {
|
|||||||
|
|
||||||
static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
|
static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
|
||||||
|
|
||||||
struct smack_known smack_cipso_option = {
|
|
||||||
.smk_known = SMACK_CIPSO_OPTION,
|
|
||||||
.smk_secid = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Values for parsing cipso rules
|
* Values for parsing cipso rules
|
||||||
* SMK_DIGITLEN: Length of a digit field in a rule.
|
* SMK_DIGITLEN: Length of a digit field in a rule.
|
||||||
@@ -1047,92 +1052,90 @@ static const struct file_operations smk_cipso2_ops = {
|
|||||||
* Seq_file read operations for /smack/netlabel
|
* Seq_file read operations for /smack/netlabel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
|
static void *net4addr_seq_start(struct seq_file *s, loff_t *pos)
|
||||||
{
|
{
|
||||||
return smk_seq_start(s, pos, &smk_netlbladdr_list);
|
return smk_seq_start(s, pos, &smk_net4addr_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
|
static void *net4addr_seq_next(struct seq_file *s, void *v, loff_t *pos)
|
||||||
{
|
{
|
||||||
return smk_seq_next(s, v, pos, &smk_netlbladdr_list);
|
return smk_seq_next(s, v, pos, &smk_net4addr_list);
|
||||||
}
|
}
|
||||||
#define BEBITS (sizeof(__be32) * 8)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print host/label pairs
|
* Print host/label pairs
|
||||||
*/
|
*/
|
||||||
static int netlbladdr_seq_show(struct seq_file *s, void *v)
|
static int net4addr_seq_show(struct seq_file *s, void *v)
|
||||||
{
|
{
|
||||||
struct list_head *list = v;
|
struct list_head *list = v;
|
||||||
struct smk_netlbladdr *skp =
|
struct smk_net4addr *skp =
|
||||||
list_entry_rcu(list, struct smk_netlbladdr, list);
|
list_entry_rcu(list, struct smk_net4addr, list);
|
||||||
unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
|
char *kp = SMACK_CIPSO_OPTION;
|
||||||
int maskn;
|
|
||||||
u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
|
|
||||||
|
|
||||||
for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++);
|
if (skp->smk_label != NULL)
|
||||||
|
kp = skp->smk_label->smk_known;
|
||||||
seq_printf(s, "%u.%u.%u.%u/%d %s\n",
|
seq_printf(s, "%pI4/%d %s\n", &skp->smk_host.s_addr,
|
||||||
hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label->smk_known);
|
skp->smk_masks, kp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct seq_operations netlbladdr_seq_ops = {
|
static const struct seq_operations net4addr_seq_ops = {
|
||||||
.start = netlbladdr_seq_start,
|
.start = net4addr_seq_start,
|
||||||
.next = netlbladdr_seq_next,
|
.next = net4addr_seq_next,
|
||||||
.show = netlbladdr_seq_show,
|
.show = net4addr_seq_show,
|
||||||
.stop = smk_seq_stop,
|
.stop = smk_seq_stop,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smk_open_netlbladdr - open() for /smack/netlabel
|
* smk_open_net4addr - open() for /smack/netlabel
|
||||||
* @inode: inode structure representing file
|
* @inode: inode structure representing file
|
||||||
* @file: "netlabel" file pointer
|
* @file: "netlabel" file pointer
|
||||||
*
|
*
|
||||||
* Connect our netlbladdr_seq_* operations with /smack/netlabel
|
* Connect our net4addr_seq_* operations with /smack/netlabel
|
||||||
* file_operations
|
* file_operations
|
||||||
*/
|
*/
|
||||||
static int smk_open_netlbladdr(struct inode *inode, struct file *file)
|
static int smk_open_net4addr(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
return seq_open(file, &netlbladdr_seq_ops);
|
return seq_open(file, &net4addr_seq_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smk_netlbladdr_insert
|
* smk_net4addr_insert
|
||||||
* @new : netlabel to insert
|
* @new : netlabel to insert
|
||||||
*
|
*
|
||||||
* This helper insert netlabel in the smack_netlbladdrs list
|
* This helper insert netlabel in the smack_net4addrs list
|
||||||
* sorted by netmask length (longest to smallest)
|
* sorted by netmask length (longest to smallest)
|
||||||
* locked by &smk_netlbladdr_lock in smk_write_netlbladdr
|
* locked by &smk_net4addr_lock in smk_write_net4addr
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
|
static void smk_net4addr_insert(struct smk_net4addr *new)
|
||||||
{
|
{
|
||||||
struct smk_netlbladdr *m, *m_next;
|
struct smk_net4addr *m;
|
||||||
|
struct smk_net4addr *m_next;
|
||||||
|
|
||||||
if (list_empty(&smk_netlbladdr_list)) {
|
if (list_empty(&smk_net4addr_list)) {
|
||||||
list_add_rcu(&new->list, &smk_netlbladdr_list);
|
list_add_rcu(&new->list, &smk_net4addr_list);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m = list_entry_rcu(smk_netlbladdr_list.next,
|
m = list_entry_rcu(smk_net4addr_list.next,
|
||||||
struct smk_netlbladdr, list);
|
struct smk_net4addr, list);
|
||||||
|
|
||||||
/* the comparison '>' is a bit hacky, but works */
|
/* the comparison '>' is a bit hacky, but works */
|
||||||
if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
|
if (new->smk_masks > m->smk_masks) {
|
||||||
list_add_rcu(&new->list, &smk_netlbladdr_list);
|
list_add_rcu(&new->list, &smk_net4addr_list);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) {
|
list_for_each_entry_rcu(m, &smk_net4addr_list, list) {
|
||||||
if (list_is_last(&m->list, &smk_netlbladdr_list)) {
|
if (list_is_last(&m->list, &smk_net4addr_list)) {
|
||||||
list_add_rcu(&new->list, &m->list);
|
list_add_rcu(&new->list, &m->list);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_next = list_entry_rcu(m->list.next,
|
m_next = list_entry_rcu(m->list.next,
|
||||||
struct smk_netlbladdr, list);
|
struct smk_net4addr, list);
|
||||||
if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) {
|
if (new->smk_masks > m_next->smk_masks) {
|
||||||
list_add_rcu(&new->list, &m->list);
|
list_add_rcu(&new->list, &m->list);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1141,28 +1144,29 @@ static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smk_write_netlbladdr - write() for /smack/netlabel
|
* smk_write_net4addr - write() for /smack/netlabel
|
||||||
* @file: file pointer, not actually used
|
* @file: file pointer, not actually used
|
||||||
* @buf: where to get the data from
|
* @buf: where to get the data from
|
||||||
* @count: bytes sent
|
* @count: bytes sent
|
||||||
* @ppos: where to start
|
* @ppos: where to start
|
||||||
*
|
*
|
||||||
* Accepts only one netlbladdr per write call.
|
* Accepts only one net4addr per write call.
|
||||||
* Returns number of bytes written or error code, as appropriate
|
* Returns number of bytes written or error code, as appropriate
|
||||||
*/
|
*/
|
||||||
static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
|
static ssize_t smk_write_net4addr(struct file *file, const char __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct smk_netlbladdr *snp;
|
struct smk_net4addr *snp;
|
||||||
struct sockaddr_in newname;
|
struct sockaddr_in newname;
|
||||||
char *smack;
|
char *smack;
|
||||||
struct smack_known *skp;
|
struct smack_known *skp = NULL;
|
||||||
char *data;
|
char *data;
|
||||||
char *host = (char *)&newname.sin_addr.s_addr;
|
char *host = (char *)&newname.sin_addr.s_addr;
|
||||||
int rc;
|
int rc;
|
||||||
struct netlbl_audit audit_info;
|
struct netlbl_audit audit_info;
|
||||||
struct in_addr mask;
|
struct in_addr mask;
|
||||||
unsigned int m;
|
unsigned int m;
|
||||||
|
unsigned int masks;
|
||||||
int found;
|
int found;
|
||||||
u32 mask_bits = (1<<31);
|
u32 mask_bits = (1<<31);
|
||||||
__be32 nsa;
|
__be32 nsa;
|
||||||
@@ -1200,7 +1204,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
|
|||||||
data[count] = '\0';
|
data[count] = '\0';
|
||||||
|
|
||||||
rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%u %s",
|
rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%u %s",
|
||||||
&host[0], &host[1], &host[2], &host[3], &m, smack);
|
&host[0], &host[1], &host[2], &host[3], &masks, smack);
|
||||||
if (rc != 6) {
|
if (rc != 6) {
|
||||||
rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
|
rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
|
||||||
&host[0], &host[1], &host[2], &host[3], smack);
|
&host[0], &host[1], &host[2], &host[3], smack);
|
||||||
@@ -1209,8 +1213,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
|
|||||||
goto free_out;
|
goto free_out;
|
||||||
}
|
}
|
||||||
m = BEBITS;
|
m = BEBITS;
|
||||||
|
masks = 32;
|
||||||
}
|
}
|
||||||
if (m > BEBITS) {
|
if (masks > BEBITS) {
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto free_out;
|
goto free_out;
|
||||||
}
|
}
|
||||||
@@ -1225,16 +1230,16 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
|
|||||||
goto free_out;
|
goto free_out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* check known options */
|
/*
|
||||||
if (strcmp(smack, smack_cipso_option.smk_known) == 0)
|
* Only the -CIPSO option is supported for IPv4
|
||||||
skp = &smack_cipso_option;
|
*/
|
||||||
else {
|
if (strcmp(smack, SMACK_CIPSO_OPTION) != 0) {
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto free_out;
|
goto free_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (temp_mask = 0; m > 0; m--) {
|
for (m = masks, temp_mask = 0; m > 0; m--) {
|
||||||
temp_mask |= mask_bits;
|
temp_mask |= mask_bits;
|
||||||
mask_bits >>= 1;
|
mask_bits >>= 1;
|
||||||
}
|
}
|
||||||
@@ -1245,14 +1250,13 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
|
|||||||
* Only allow one writer at a time. Writes should be
|
* Only allow one writer at a time. Writes should be
|
||||||
* quite rare and small in any case.
|
* quite rare and small in any case.
|
||||||
*/
|
*/
|
||||||
mutex_lock(&smk_netlbladdr_lock);
|
mutex_lock(&smk_net4addr_lock);
|
||||||
|
|
||||||
nsa = newname.sin_addr.s_addr;
|
nsa = newname.sin_addr.s_addr;
|
||||||
/* try to find if the prefix is already in the list */
|
/* try to find if the prefix is already in the list */
|
||||||
found = 0;
|
found = 0;
|
||||||
list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) {
|
list_for_each_entry_rcu(snp, &smk_net4addr_list, list) {
|
||||||
if (snp->smk_host.sin_addr.s_addr == nsa &&
|
if (snp->smk_host.s_addr == nsa && snp->smk_masks == masks) {
|
||||||
snp->smk_mask.s_addr == mask.s_addr) {
|
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1265,17 +1269,20 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
|
|||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
else {
|
else {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
snp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
|
snp->smk_host.s_addr = newname.sin_addr.s_addr;
|
||||||
snp->smk_mask.s_addr = mask.s_addr;
|
snp->smk_mask.s_addr = mask.s_addr;
|
||||||
snp->smk_label = skp;
|
snp->smk_label = skp;
|
||||||
smk_netlbladdr_insert(snp);
|
snp->smk_masks = masks;
|
||||||
|
smk_net4addr_insert(snp);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* we delete the unlabeled entry, only if the previous label
|
/*
|
||||||
* wasn't the special CIPSO option */
|
* Delete the unlabeled entry, only if the previous label
|
||||||
if (snp->smk_label != &smack_cipso_option)
|
* wasn't the special CIPSO option
|
||||||
|
*/
|
||||||
|
if (snp->smk_label != NULL)
|
||||||
rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
|
rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
|
||||||
&snp->smk_host.sin_addr, &snp->smk_mask,
|
&snp->smk_host, &snp->smk_mask,
|
||||||
PF_INET, &audit_info);
|
PF_INET, &audit_info);
|
||||||
else
|
else
|
||||||
rc = 0;
|
rc = 0;
|
||||||
@@ -1287,15 +1294,15 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
|
|||||||
* this host so that incoming packets get labeled.
|
* this host so that incoming packets get labeled.
|
||||||
* but only if we didn't get the special CIPSO option
|
* but only if we didn't get the special CIPSO option
|
||||||
*/
|
*/
|
||||||
if (rc == 0 && skp != &smack_cipso_option)
|
if (rc == 0 && skp != NULL)
|
||||||
rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
|
rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
|
||||||
&snp->smk_host.sin_addr, &snp->smk_mask, PF_INET,
|
&snp->smk_host, &snp->smk_mask, PF_INET,
|
||||||
snp->smk_label->smk_secid, &audit_info);
|
snp->smk_label->smk_secid, &audit_info);
|
||||||
|
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
rc = count;
|
rc = count;
|
||||||
|
|
||||||
mutex_unlock(&smk_netlbladdr_lock);
|
mutex_unlock(&smk_net4addr_lock);
|
||||||
|
|
||||||
free_out:
|
free_out:
|
||||||
kfree(smack);
|
kfree(smack);
|
||||||
@@ -1305,14 +1312,279 @@ free_data_out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct file_operations smk_netlbladdr_ops = {
|
static const struct file_operations smk_net4addr_ops = {
|
||||||
.open = smk_open_netlbladdr,
|
.open = smk_open_net4addr,
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.llseek = seq_lseek,
|
.llseek = seq_lseek,
|
||||||
.write = smk_write_netlbladdr,
|
.write = smk_write_net4addr,
|
||||||
.release = seq_release,
|
.release = seq_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
/*
|
||||||
|
* Seq_file read operations for /smack/netlabel6
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void *net6addr_seq_start(struct seq_file *s, loff_t *pos)
|
||||||
|
{
|
||||||
|
return smk_seq_start(s, pos, &smk_net6addr_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *net6addr_seq_next(struct seq_file *s, void *v, loff_t *pos)
|
||||||
|
{
|
||||||
|
return smk_seq_next(s, v, pos, &smk_net6addr_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print host/label pairs
|
||||||
|
*/
|
||||||
|
static int net6addr_seq_show(struct seq_file *s, void *v)
|
||||||
|
{
|
||||||
|
struct list_head *list = v;
|
||||||
|
struct smk_net6addr *skp =
|
||||||
|
list_entry(list, struct smk_net6addr, list);
|
||||||
|
|
||||||
|
if (skp->smk_label != NULL)
|
||||||
|
seq_printf(s, "%pI6/%d %s\n", &skp->smk_host, skp->smk_masks,
|
||||||
|
skp->smk_label->smk_known);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct seq_operations net6addr_seq_ops = {
|
||||||
|
.start = net6addr_seq_start,
|
||||||
|
.next = net6addr_seq_next,
|
||||||
|
.show = net6addr_seq_show,
|
||||||
|
.stop = smk_seq_stop,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smk_open_net6addr - open() for /smack/netlabel
|
||||||
|
* @inode: inode structure representing file
|
||||||
|
* @file: "netlabel" file pointer
|
||||||
|
*
|
||||||
|
* Connect our net6addr_seq_* operations with /smack/netlabel
|
||||||
|
* file_operations
|
||||||
|
*/
|
||||||
|
static int smk_open_net6addr(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return seq_open(file, &net6addr_seq_ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smk_net6addr_insert
|
||||||
|
* @new : entry to insert
|
||||||
|
*
|
||||||
|
* This inserts an entry in the smack_net6addrs list
|
||||||
|
* sorted by netmask length (longest to smallest)
|
||||||
|
* locked by &smk_net6addr_lock in smk_write_net6addr
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void smk_net6addr_insert(struct smk_net6addr *new)
|
||||||
|
{
|
||||||
|
struct smk_net6addr *m_next;
|
||||||
|
struct smk_net6addr *m;
|
||||||
|
|
||||||
|
if (list_empty(&smk_net6addr_list)) {
|
||||||
|
list_add_rcu(&new->list, &smk_net6addr_list);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m = list_entry_rcu(smk_net6addr_list.next,
|
||||||
|
struct smk_net6addr, list);
|
||||||
|
|
||||||
|
if (new->smk_masks > m->smk_masks) {
|
||||||
|
list_add_rcu(&new->list, &smk_net6addr_list);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry_rcu(m, &smk_net6addr_list, list) {
|
||||||
|
if (list_is_last(&m->list, &smk_net6addr_list)) {
|
||||||
|
list_add_rcu(&new->list, &m->list);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_next = list_entry_rcu(m->list.next,
|
||||||
|
struct smk_net6addr, list);
|
||||||
|
if (new->smk_masks > m_next->smk_masks) {
|
||||||
|
list_add_rcu(&new->list, &m->list);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smk_write_net6addr - write() for /smack/netlabel
|
||||||
|
* @file: file pointer, not actually used
|
||||||
|
* @buf: where to get the data from
|
||||||
|
* @count: bytes sent
|
||||||
|
* @ppos: where to start
|
||||||
|
*
|
||||||
|
* Accepts only one net6addr per write call.
|
||||||
|
* Returns number of bytes written or error code, as appropriate
|
||||||
|
*/
|
||||||
|
static ssize_t smk_write_net6addr(struct file *file, const char __user *buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct smk_net6addr *snp;
|
||||||
|
struct in6_addr newname;
|
||||||
|
struct in6_addr fullmask;
|
||||||
|
struct smack_known *skp = NULL;
|
||||||
|
char *smack;
|
||||||
|
char *data;
|
||||||
|
int rc = 0;
|
||||||
|
int found = 0;
|
||||||
|
int i;
|
||||||
|
unsigned int scanned[8];
|
||||||
|
unsigned int m;
|
||||||
|
unsigned int mask = 128;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must have privilege.
|
||||||
|
* No partial writes.
|
||||||
|
* Enough data must be present.
|
||||||
|
* "<addr/mask, as a:b:c:d:e:f:g:h/e><space><label>"
|
||||||
|
* "<addr, as a:b:c:d:e:f:g:h><space><label>"
|
||||||
|
*/
|
||||||
|
if (!smack_privileged(CAP_MAC_ADMIN))
|
||||||
|
return -EPERM;
|
||||||
|
if (*ppos != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (count < SMK_NETLBLADDRMIN)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
data = kzalloc(count + 1, GFP_KERNEL);
|
||||||
|
if (data == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (copy_from_user(data, buf, count) != 0) {
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto free_data_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
smack = kzalloc(count + 1, GFP_KERNEL);
|
||||||
|
if (smack == NULL) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto free_data_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
data[count] = '\0';
|
||||||
|
|
||||||
|
i = sscanf(data, "%x:%x:%x:%x:%x:%x:%x:%x/%u %s",
|
||||||
|
&scanned[0], &scanned[1], &scanned[2], &scanned[3],
|
||||||
|
&scanned[4], &scanned[5], &scanned[6], &scanned[7],
|
||||||
|
&mask, smack);
|
||||||
|
if (i != 10) {
|
||||||
|
i = sscanf(data, "%x:%x:%x:%x:%x:%x:%x:%x %s",
|
||||||
|
&scanned[0], &scanned[1], &scanned[2],
|
||||||
|
&scanned[3], &scanned[4], &scanned[5],
|
||||||
|
&scanned[6], &scanned[7], smack);
|
||||||
|
if (i != 9) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto free_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mask > 128) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto free_out;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (scanned[i] > 0xffff) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto free_out;
|
||||||
|
}
|
||||||
|
newname.s6_addr16[i] = htons(scanned[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If smack begins with '-', it is an option, don't import it
|
||||||
|
*/
|
||||||
|
if (smack[0] != '-') {
|
||||||
|
skp = smk_import_entry(smack, 0);
|
||||||
|
if (skp == NULL) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto free_out;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Only -DELETE is supported for IPv6
|
||||||
|
*/
|
||||||
|
if (strcmp(smack, SMACK_DELETE_OPTION) != 0) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto free_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, m = mask; i < 8; i++) {
|
||||||
|
if (m >= 16) {
|
||||||
|
fullmask.s6_addr16[i] = 0xffff;
|
||||||
|
m -= 16;
|
||||||
|
} else if (m > 0) {
|
||||||
|
fullmask.s6_addr16[i] = (1 << m) - 1;
|
||||||
|
m = 0;
|
||||||
|
} else
|
||||||
|
fullmask.s6_addr16[i] = 0;
|
||||||
|
newname.s6_addr16[i] &= fullmask.s6_addr16[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only allow one writer at a time. Writes should be
|
||||||
|
* quite rare and small in any case.
|
||||||
|
*/
|
||||||
|
mutex_lock(&smk_net6addr_lock);
|
||||||
|
/*
|
||||||
|
* Try to find the prefix in the list
|
||||||
|
*/
|
||||||
|
list_for_each_entry_rcu(snp, &smk_net6addr_list, list) {
|
||||||
|
if (mask != snp->smk_masks)
|
||||||
|
continue;
|
||||||
|
for (found = 1, i = 0; i < 8; i++) {
|
||||||
|
if (newname.s6_addr16[i] !=
|
||||||
|
snp->smk_host.s6_addr16[i]) {
|
||||||
|
found = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found == 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (found == 0) {
|
||||||
|
snp = kzalloc(sizeof(*snp), GFP_KERNEL);
|
||||||
|
if (snp == NULL)
|
||||||
|
rc = -ENOMEM;
|
||||||
|
else {
|
||||||
|
snp->smk_host = newname;
|
||||||
|
snp->smk_mask = fullmask;
|
||||||
|
snp->smk_masks = mask;
|
||||||
|
snp->smk_label = skp;
|
||||||
|
smk_net6addr_insert(snp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
snp->smk_label = skp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == 0)
|
||||||
|
rc = count;
|
||||||
|
|
||||||
|
mutex_unlock(&smk_net6addr_lock);
|
||||||
|
|
||||||
|
free_out:
|
||||||
|
kfree(smack);
|
||||||
|
free_data_out:
|
||||||
|
kfree(data);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations smk_net6addr_ops = {
|
||||||
|
.open = smk_open_net6addr,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.write = smk_write_net6addr,
|
||||||
|
.release = seq_release,
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_IPV6 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smk_read_doi - read() for /smack/doi
|
* smk_read_doi - read() for /smack/doi
|
||||||
* @filp: file pointer, not actually used
|
* @filp: file pointer, not actually used
|
||||||
@@ -2320,11 +2592,7 @@ static const struct file_operations smk_revoke_subj_ops = {
|
|||||||
*/
|
*/
|
||||||
static int smk_init_sysfs(void)
|
static int smk_init_sysfs(void)
|
||||||
{
|
{
|
||||||
int err;
|
return sysfs_create_mount_point(fs_kobj, "smackfs");
|
||||||
err = sysfs_create_mount_point(fs_kobj, "smackfs");
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2519,8 +2787,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
|
|||||||
"direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
|
"direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
|
||||||
[SMK_AMBIENT] = {
|
[SMK_AMBIENT] = {
|
||||||
"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
|
"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
|
||||||
[SMK_NETLBLADDR] = {
|
[SMK_NET4ADDR] = {
|
||||||
"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
|
"netlabel", &smk_net4addr_ops, S_IRUGO|S_IWUSR},
|
||||||
[SMK_ONLYCAP] = {
|
[SMK_ONLYCAP] = {
|
||||||
"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
|
"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
|
||||||
[SMK_LOGGING] = {
|
[SMK_LOGGING] = {
|
||||||
@@ -2552,6 +2820,10 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
|
|||||||
[SMK_UNCONFINED] = {
|
[SMK_UNCONFINED] = {
|
||||||
"unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR},
|
"unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR},
|
||||||
#endif
|
#endif
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
|
[SMK_NET6ADDR] = {
|
||||||
|
"ipv6host", &smk_net6addr_ops, S_IRUGO|S_IWUSR},
|
||||||
|
#endif /* CONFIG_IPV6 */
|
||||||
/* last one */
|
/* last one */
|
||||||
{""}
|
{""}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user