Commit 30bc9456 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6:
  security: enhance DEFAULT_MMAP_MIN_ADDR description
  SELinux: add netport.[ch]
  SELinux: Add network port SID cache
  SELinux: turn mount options strings into defines
  selinux/ss/services.c should #include <linux/selinux.h>
  selinux: introduce permissive types
  selinux: remove ptrace_sid
  SELinux: requesting no permissions in avc_has_perm_noaudit is a BUG()
  security: code cleanup
  security: replace remaining __FUNCTION__ occurrences
  SELinux: create new open permission
  selinux: selinux/netlabel.c should #include "netlabel.h"
  SELinux: unify printk messages
  SELinux: remove unused backpointers from security objects
  SELinux: Correct the NetLabel locking for the sk_security_struct
parents 4cba84b5 5f46ce14
...@@ -113,10 +113,12 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR ...@@ -113,10 +113,12 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
from userspace allocation. Keeping a user from writing to low pages from userspace allocation. Keeping a user from writing to low pages
can help reduce the impact of kernel NULL pointer bugs. can help reduce the impact of kernel NULL pointer bugs.
For most users with lots of address space a value of 65536 is For most ia64, ppc64 and x86 users with lots of address space
reasonable and should cause no problems. Programs which use vm86 a value of 65536 is reasonable and should cause no problems.
functionality would either need additional permissions from either On arm and other archs it should not be higher than 32768.
the LSM or the capabilities module or have this protection disabled. Programs which use vm86 functionality would either need additional
permissions from either the LSM or the capabilities module or have
this protection disabled.
This value can be changed after boot using the This value can be changed after boot using the
/proc/sys/vm/mmap_min_addr tunable. /proc/sys/vm/mmap_min_addr tunable.
......
...@@ -267,7 +267,7 @@ static int get_file_caps(struct linux_binprm *bprm) ...@@ -267,7 +267,7 @@ static int get_file_caps(struct linux_binprm *bprm)
rc = cap_from_disk(&vcaps, bprm, rc); rc = cap_from_disk(&vcaps, bprm, rc);
if (rc) if (rc)
printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
__FUNCTION__, rc, bprm->filename); __func__, rc, bprm->filename);
out: out:
dput(dentry); dput(dentry);
...@@ -302,7 +302,7 @@ int cap_bprm_set_security (struct linux_binprm *bprm) ...@@ -302,7 +302,7 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
ret = get_file_caps(bprm); ret = get_file_caps(bprm);
if (ret) if (ret)
printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n", printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
__FUNCTION__, ret, bprm->filename); __func__, ret, bprm->filename);
/* To support inheritance of root-permissions and suid-root /* To support inheritance of root-permissions and suid-root
* executables under compatibility mode, we raise all three * executables under compatibility mode, we raise all three
......
...@@ -22,16 +22,16 @@ void no_printk(const char *fmt, ...) ...@@ -22,16 +22,16 @@ void no_printk(const char *fmt, ...)
#ifdef __KDEBUG #ifdef __KDEBUG
#define kenter(FMT, ...) \ #define kenter(FMT, ...) \
printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__) printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
#define kleave(FMT, ...) \ #define kleave(FMT, ...) \
printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__) printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
#define kdebug(FMT, ...) \ #define kdebug(FMT, ...) \
printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__) printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__)
#else #else
#define kenter(FMT, ...) \ #define kenter(FMT, ...) \
no_printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__) no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
#define kleave(FMT, ...) \ #define kleave(FMT, ...) \
no_printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__) no_printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
#define kdebug(FMT, ...) \ #define kdebug(FMT, ...) \
no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__) no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__)
#endif #endif
......
...@@ -49,7 +49,7 @@ module_param(debug, bool, 0600); ...@@ -49,7 +49,7 @@ module_param(debug, bool, 0600);
do { \ do { \
if (debug) \ if (debug) \
printk(KERN_DEBUG "%s: %s: " fmt , \ printk(KERN_DEBUG "%s: %s: " fmt , \
MY_NAME , __FUNCTION__ , \ MY_NAME , __func__ , \
## arg); \ ## arg); \
} while (0) } while (0)
......
...@@ -57,7 +57,7 @@ int __init security_init(void) ...@@ -57,7 +57,7 @@ int __init security_init(void)
if (verify(&dummy_security_ops)) { if (verify(&dummy_security_ops)) {
printk(KERN_ERR "%s could not verify " printk(KERN_ERR "%s could not verify "
"dummy_security_ops structure.\n", __FUNCTION__); "dummy_security_ops structure.\n", __func__);
return -EIO; return -EIO;
} }
...@@ -82,7 +82,7 @@ int register_security(struct security_operations *ops) ...@@ -82,7 +82,7 @@ int register_security(struct security_operations *ops)
{ {
if (verify(ops)) { if (verify(ops)) {
printk(KERN_DEBUG "%s could not verify " printk(KERN_DEBUG "%s could not verify "
"security_operations structure.\n", __FUNCTION__); "security_operations structure.\n", __func__);
return -EINVAL; return -EINVAL;
} }
...@@ -110,13 +110,13 @@ int mod_reg_security(const char *name, struct security_operations *ops) ...@@ -110,13 +110,13 @@ int mod_reg_security(const char *name, struct security_operations *ops)
{ {
if (verify(ops)) { if (verify(ops)) {
printk(KERN_INFO "%s could not verify " printk(KERN_INFO "%s could not verify "
"security operations.\n", __FUNCTION__); "security operations.\n", __func__);
return -EINVAL; return -EINVAL;
} }
if (ops == security_ops) { if (ops == security_ops) {
printk(KERN_INFO "%s security operations " printk(KERN_INFO "%s security operations "
"already registered.\n", __FUNCTION__); "already registered.\n", __func__);
return -EINVAL; return -EINVAL;
} }
......
...@@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX ...@@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX
config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
int "NSA SELinux maximum supported policy format version value" int "NSA SELinux maximum supported policy format version value"
depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
range 15 22 range 15 23
default 19 default 19
help help
This option sets the value for the maximum policy format version This option sets the value for the maximum policy format version
......
...@@ -11,6 +11,7 @@ selinux-y := avc.o \ ...@@ -11,6 +11,7 @@ selinux-y := avc.o \
nlmsgtab.o \ nlmsgtab.o \
netif.o \ netif.o \
netnode.o \ netnode.o \
netport.o \
exports.o exports.o
selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
......
...@@ -871,6 +871,8 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, ...@@ -871,6 +871,8 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
int rc = 0; int rc = 0;
u32 denied; u32 denied;
BUG_ON(!requested);
rcu_read_lock(); rcu_read_lock();
node = avc_lookup(ssid, tsid, tclass, requested); node = avc_lookup(ssid, tsid, tclass, requested);
...@@ -890,13 +892,14 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, ...@@ -890,13 +892,14 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
denied = requested & ~(p_ae->avd.allowed); denied = requested & ~(p_ae->avd.allowed);
if (!requested || denied) { if (denied) {
if (selinux_enforcing || (flags & AVC_STRICT)) if (flags & AVC_STRICT)
rc = -EACCES; rc = -EACCES;
else if (!selinux_enforcing || security_permissive_sid(ssid))
avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
tsid, tclass);
else else
if (node) rc = -EACCES;
avc_update_node(AVC_CALLBACK_GRANT,requested,
ssid,tsid,tclass);
} }
rcu_read_unlock(); rcu_read_unlock();
......
This diff is collapsed.
...@@ -14,12 +14,17 @@ ...@@ -14,12 +14,17 @@
S_(SECCLASS_DIR, DIR__REPARENT, "reparent") S_(SECCLASS_DIR, DIR__REPARENT, "reparent")
S_(SECCLASS_DIR, DIR__SEARCH, "search") S_(SECCLASS_DIR, DIR__SEARCH, "search")
S_(SECCLASS_DIR, DIR__RMDIR, "rmdir") S_(SECCLASS_DIR, DIR__RMDIR, "rmdir")
S_(SECCLASS_DIR, DIR__OPEN, "open")
S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans") S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans")
S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint") S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
S_(SECCLASS_FILE, FILE__EXECMOD, "execmod") S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
S_(SECCLASS_FILE, FILE__OPEN, "open")
S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans") S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint") S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod") S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
S_(SECCLASS_CHR_FILE, CHR_FILE__OPEN, "open")
S_(SECCLASS_BLK_FILE, BLK_FILE__OPEN, "open")
S_(SECCLASS_FIFO_FILE, FIFO_FILE__OPEN, "open")
S_(SECCLASS_FD, FD__USE, "use") S_(SECCLASS_FD, FD__USE, "use")
S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto") S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto")
S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn") S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn")
......
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
#define DIR__REPARENT 0x00080000UL #define DIR__REPARENT 0x00080000UL
#define DIR__SEARCH 0x00100000UL #define DIR__SEARCH 0x00100000UL
#define DIR__RMDIR 0x00200000UL #define DIR__RMDIR 0x00200000UL
#define DIR__OPEN 0x00400000UL
#define FILE__IOCTL 0x00000001UL #define FILE__IOCTL 0x00000001UL
#define FILE__READ 0x00000002UL #define FILE__READ 0x00000002UL
#define FILE__WRITE 0x00000004UL #define FILE__WRITE 0x00000004UL
...@@ -99,6 +100,7 @@ ...@@ -99,6 +100,7 @@
#define FILE__EXECUTE_NO_TRANS 0x00020000UL #define FILE__EXECUTE_NO_TRANS 0x00020000UL
#define FILE__ENTRYPOINT 0x00040000UL #define FILE__ENTRYPOINT 0x00040000UL
#define FILE__EXECMOD 0x00080000UL #define FILE__EXECMOD 0x00080000UL
#define FILE__OPEN 0x00100000UL
#define LNK_FILE__IOCTL 0x00000001UL #define LNK_FILE__IOCTL 0x00000001UL
#define LNK_FILE__READ 0x00000002UL #define LNK_FILE__READ 0x00000002UL
#define LNK_FILE__WRITE 0x00000004UL #define LNK_FILE__WRITE 0x00000004UL
...@@ -136,6 +138,7 @@ ...@@ -136,6 +138,7 @@
#define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL #define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL
#define CHR_FILE__ENTRYPOINT 0x00040000UL #define CHR_FILE__ENTRYPOINT 0x00040000UL
#define CHR_FILE__EXECMOD 0x00080000UL #define CHR_FILE__EXECMOD 0x00080000UL
#define CHR_FILE__OPEN 0x00100000UL
#define BLK_FILE__IOCTL 0x00000001UL #define BLK_FILE__IOCTL 0x00000001UL
#define BLK_FILE__READ 0x00000002UL #define BLK_FILE__READ 0x00000002UL
#define BLK_FILE__WRITE 0x00000004UL #define BLK_FILE__WRITE 0x00000004UL
...@@ -153,6 +156,7 @@ ...@@ -153,6 +156,7 @@
#define BLK_FILE__SWAPON 0x00004000UL #define BLK_FILE__SWAPON 0x00004000UL
#define BLK_FILE__QUOTAON 0x00008000UL #define BLK_FILE__QUOTAON 0x00008000UL
#define BLK_FILE__MOUNTON 0x00010000UL #define BLK_FILE__MOUNTON 0x00010000UL
#define BLK_FILE__OPEN 0x00020000UL
#define SOCK_FILE__IOCTL 0x00000001UL #define SOCK_FILE__IOCTL 0x00000001UL
#define SOCK_FILE__READ 0x00000002UL #define SOCK_FILE__READ 0x00000002UL
#define SOCK_FILE__WRITE 0x00000004UL #define SOCK_FILE__WRITE 0x00000004UL
...@@ -187,6 +191,7 @@ ...@@ -187,6 +191,7 @@
#define FIFO_FILE__SWAPON 0x00004000UL #define FIFO_FILE__SWAPON 0x00004000UL
#define FIFO_FILE__QUOTAON 0x00008000UL #define FIFO_FILE__QUOTAON 0x00008000UL
#define FIFO_FILE__MOUNTON 0x00010000UL #define FIFO_FILE__MOUNTON 0x00010000UL
#define FIFO_FILE__OPEN 0x00020000UL
#define FD__USE 0x00000001UL #define FD__USE 0x00000001UL
#define SOCKET__IOCTL 0x00000001UL #define SOCKET__IOCTL 0x00000001UL
#define SOCKET__READ 0x00000002UL #define SOCKET__READ 0x00000002UL
......
...@@ -41,10 +41,6 @@ void selinux_netlbl_cache_invalidate(void); ...@@ -41,10 +41,6 @@ void selinux_netlbl_cache_invalidate(void);
void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
int family); int family);
void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
int family);
void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
struct sk_security_struct *newssec);
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
u16 family, u16 family,
...@@ -73,18 +69,6 @@ static inline void selinux_netlbl_sk_security_reset( ...@@ -73,18 +69,6 @@ static inline void selinux_netlbl_sk_security_reset(
{ {
return; return;
} }
static inline void selinux_netlbl_sk_security_init(
struct sk_security_struct *ssec,
int family)
{
return;
}
static inline void selinux_netlbl_sk_security_clone(
struct sk_security_struct *ssec,
struct sk_security_struct *newssec)
{
return;
}
static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
u16 family, u16 family,
......
/*
* Network port table
*
* SELinux must keep a mapping of network ports to labels/SIDs. This
* mapping is maintained as part of the normal policy but a fast cache is
* needed to reduce the lookup overhead.
*
* Author: Paul Moore <paul.moore@hp.com>
*
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2008
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _SELINUX_NETPORT_H
#define _SELINUX_NETPORT_H
int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid);
#endif
...@@ -28,14 +28,12 @@ ...@@ -28,14 +28,12 @@
#include "avc.h" #include "avc.h"
struct task_security_struct { struct task_security_struct {
struct task_struct *task; /* back pointer to task object */
u32 osid; /* SID prior to last execve */ u32 osid; /* SID prior to last execve */
u32 sid; /* current SID */ u32 sid; /* current SID */
u32 exec_sid; /* exec SID */ u32 exec_sid; /* exec SID */
u32 create_sid; /* fscreate SID */ u32 create_sid; /* fscreate SID */
u32 keycreate_sid; /* keycreate SID */ u32 keycreate_sid; /* keycreate SID */
u32 sockcreate_sid; /* fscreate SID */ u32 sockcreate_sid; /* fscreate SID */
u32 ptrace_sid; /* SID of ptrace parent */
}; };
struct inode_security_struct { struct inode_security_struct {
...@@ -50,7 +48,6 @@ struct inode_security_struct { ...@@ -50,7 +48,6 @@ struct inode_security_struct {
}; };
struct file_security_struct { struct file_security_struct {
struct file *file; /* back pointer to file object */
u32 sid; /* SID of open file description */ u32 sid; /* SID of open file description */
u32 fown_sid; /* SID of file owner (for SIGIO) */ u32 fown_sid; /* SID of file owner (for SIGIO) */
u32 isid; /* SID of inode at the time of file open */ u32 isid; /* SID of inode at the time of file open */
...@@ -73,18 +70,15 @@ struct superblock_security_struct { ...@@ -73,18 +70,15 @@ struct superblock_security_struct {
}; };
struct msg_security_struct { struct msg_security_struct {
struct msg_msg *msg; /* back pointer */
u32 sid; /* SID of message */ u32 sid; /* SID of message */
}; };
struct ipc_security_struct { struct ipc_security_struct {
struct kern_ipc_perm *ipc_perm; /* back pointer */
u16 sclass; /* security class of this object */ u16 sclass; /* security class of this object */
u32 sid; /* SID of IPC resource */ u32 sid; /* SID of IPC resource */
}; };
struct bprm_security_struct { struct bprm_security_struct {
struct linux_binprm *bprm; /* back pointer to bprm object */
u32 sid; /* SID for transformed process */ u32 sid; /* SID for transformed process */
unsigned char set; unsigned char set;
...@@ -109,8 +103,13 @@ struct netnode_security_struct { ...@@ -109,8 +103,13 @@ struct netnode_security_struct {
u16 family; /* address family */ u16 family; /* address family */
}; };
struct netport_security_struct {
u32 sid; /* SID for this node */
u16 port; /* port number */
u8 protocol; /* transport protocol */
};
struct sk_security_struct { struct sk_security_struct {
struct sock *sk; /* back pointer to sk object */
u32 sid; /* SID of this object */ u32 sid; /* SID of this object */
u32 peer_sid; /* SID of peer */ u32 peer_sid; /* SID of peer */
u16 sclass; /* sock security class */ u16 sclass; /* sock security class */
...@@ -120,12 +119,10 @@ struct sk_security_struct { ...@@ -120,12 +119,10 @@ struct sk_security_struct {
NLBL_REQUIRE, NLBL_REQUIRE,
NLBL_LABELED, NLBL_LABELED,
} nlbl_state; } nlbl_state;
spinlock_t nlbl_lock; /* protects nlbl_state */
#endif #endif
}; };
struct key_security_struct { struct key_security_struct {
struct key *obj; /* back pointer */
u32 sid; /* SID of key */ u32 sid; /* SID of key */
}; };
......
...@@ -26,13 +26,14 @@ ...@@ -26,13 +26,14 @@
#define POLICYDB_VERSION_AVTAB 20 #define POLICYDB_VERSION_AVTAB 20
#define POLICYDB_VERSION_RANGETRANS 21 #define POLICYDB_VERSION_RANGETRANS 21
#define POLICYDB_VERSION_POLCAP 22 #define POLICYDB_VERSION_POLCAP 22
#define POLICYDB_VERSION_PERMISSIVE 23
/* Range of policy versions we understand*/ /* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
#else #else
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP #define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE
#endif #endif
#define CONTEXT_MNT 0x01 #define CONTEXT_MNT 0x01
...@@ -40,6 +41,11 @@ ...@@ -40,6 +41,11 @@
#define ROOTCONTEXT_MNT 0x04 #define ROOTCONTEXT_MNT 0x04
#define DEFCONTEXT_MNT 0x08 #define DEFCONTEXT_MNT 0x08
#define CONTEXT_STR "context="
#define FSCONTEXT_STR "fscontext="
#define ROOTCONTEXT_STR "rootcontext="
#define DEFCONTEXT_STR "defcontext="
struct netlbl_lsm_secattr; struct netlbl_lsm_secattr;
extern int selinux_enabled; extern int selinux_enabled;
...@@ -48,11 +54,13 @@ extern int selinux_mls_enabled; ...@@ -48,11 +54,13 @@ extern int selinux_mls_enabled;
/* Policy capabilities */ /* Policy capabilities */
enum { enum {
POLICYDB_CAPABILITY_NETPEER, POLICYDB_CAPABILITY_NETPEER,
POLICYDB_CAPABILITY_OPENPERM,
__POLICYDB_CAPABILITY_MAX __POLICYDB_CAPABILITY_MAX
}; };
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
extern int selinux_policycap_netpeer; extern int selinux_policycap_netpeer;
extern int selinux_policycap_openperm;
int security_load_policy(void * data, size_t len); int security_load_policy(void * data, size_t len);
...@@ -67,6 +75,8 @@ struct av_decision { ...@@ -67,6 +75,8 @@ struct av_decision {
u32 seqno; u32 seqno;
}; };
int security_permissive_sid(u32 sid);
int security_compute_av(u32 ssid, u32 tsid, int security_compute_av(u32 ssid, u32 tsid,
u16 tclass, u32 requested, u16 tclass, u32 requested,
struct av_decision *avd); struct av_decision *avd);
...@@ -92,8 +102,7 @@ int security_context_to_sid_default(char *scontext, u32 scontext_len, ...@@ -92,8 +102,7 @@ int security_context_to_sid_default(char *scontext, u32 scontext_len,
int security_get_user_sids(u32 callsid, char *username, int security_get_user_sids(u32 callsid, char *username,
u32 **sids, u32 *nel); u32 **sids, u32 *nel);
int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port, int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
u32 *out_sid);
int security_netif_sid(char *name, u32 *if_sid); int security_netif_sid(char *name, u32 *if_sid);
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "objsec.h" #include "objsec.h"
#include "security.h" #include "security.h"
#include "netlabel.h"
/** /**
* selinux_netlbl_sidlookup_cached - Cache a SID lookup * selinux_netlbl_sidlookup_cached - Cache a SID lookup
...@@ -69,9 +70,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, ...@@ -69,9 +70,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
* *
* Description: * Description:
* Attempt to label a socket using the NetLabel mechanism using the given * Attempt to label a socket using the NetLabel mechanism using the given
* SID. Returns zero values on success, negative values on failure. The * SID. Returns zero values on success, negative values on failure.
* caller is responsibile for calling rcu_read_lock() before calling this
* this function and rcu_read_unlock() after this function returns.
* *
*/ */
static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
...@@ -86,11 +85,8 @@ static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) ...@@ -86,11 +85,8 @@ static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
if (rc != 0) if (rc != 0)
goto sock_setsid_return; goto sock_setsid_return;
rc = netlbl_sock_setattr(sk, &secattr); rc = netlbl_sock_setattr(sk, &secattr);
if (rc == 0) { if (rc == 0)
spin_lock_bh(&sksec->nlbl_lock);
sksec->nlbl_state = NLBL_LABELED; sksec->nlbl_state = NLBL_LABELED;
spin_unlock_bh(&sksec->nlbl_lock);
}
sock_setsid_return: sock_setsid_return:
netlbl_secattr_destroy(&secattr); netlbl_secattr_destroy(&secattr);
...@@ -128,45 +124,6 @@ void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, ...@@ -128,45 +124,6 @@ void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
ssec->nlbl_state = NLBL_UNSET; ssec->nlbl_state = NLBL_UNSET;
} }
/**
* selinux_netlbl_sk_security_init - Setup the NetLabel fields
* @ssec: the sk_security_struct
* @family: the socket family
*
* Description:
* Called when a new sk_security_struct is allocated to initialize the NetLabel
* fields.
*
*/
void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
int family)
{
/* No locking needed, we are the only one who has access to ssec */
selinux_netlbl_sk_security_reset(ssec, family);
spin_lock_init(&ssec->nlbl_lock);
}
/**
* selinux_netlbl_sk_security_clone - Copy the NetLabel fields
* @ssec: the original sk_security_struct
* @newssec: the cloned sk_security_struct
*
* Description:
* Clone the NetLabel specific sk_security_struct fields from @ssec to
* @newssec.
*
*/
void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
struct sk_security_struct *newssec)
{
/* We don't need to take newssec->nlbl_lock because we are the only
* thread with access to newssec, but we do need to take the RCU read
* lock as other threads could have access to ssec */
rcu_read_lock();
selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
rcu_read_unlock();
}
/** /**
* selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
* @skb: the packet * @skb: the packet
...@@ -221,12 +178,8 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) ...@@ -221,12 +178,8 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
struct netlbl_lsm_secattr secattr; struct netlbl_lsm_secattr secattr;
u32 nlbl_peer_sid; u32 nlbl_peer_sid;
rcu_read_lock(); if (sksec->nlbl_state != NLBL_REQUIRE)
if (sksec->nlbl_state != NLBL_REQUIRE) {
rcu_read_unlock();
return; return;
}
netlbl_secattr_init(&secattr); netlbl_secattr_init(&secattr);
if (netlbl_sock_getattr(sk, &secattr) == 0 && if (netlbl_sock_getattr(sk, &secattr) == 0 &&
...@@ -239,8 +192,6 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) ...@@ -239,8 +192,6 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
* here we will pick up the pieces in later calls to * here we will pick up the pieces in later calls to
* selinux_netlbl_inode_permission(). */ * selinux_netlbl_inode_permission(). */
selinux_netlbl_sock_setsid(sk, sksec->sid); selinux_netlbl_sock_setsid(sk, sksec->sid);
rcu_read_unlock();
} }
/** /**
...@@ -254,16 +205,13 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) ...@@ -254,16 +205,13 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
*/ */
int selinux_netlbl_socket_post_create(struct socket *sock) int selinux_netlbl_socket_post_create(struct socket *sock)
{ {
int rc = 0;
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct sk_security_struct *sksec = sk->sk_security; struct sk_security_struct *sksec = sk->sk_security;
rcu_read_lock(); if (sksec->nlbl_state != NLBL_REQUIRE)
if (sksec->nlbl_state == NLBL_REQUIRE) return 0;
rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
rcu_read_unlock();
return rc; return selinux_netlbl_sock_setsid(sk, sksec->sid);
} }
/** /**
...@@ -288,21 +236,21 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) ...@@ -288,21 +236,21 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
if (!S_ISSOCK(inode->i_mode) || if (!S_ISSOCK(inode->i_mode) ||
((mask & (MAY_WRITE | MAY_APPEND)) == 0)) ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
return 0; return 0;
sock = SOCKET_I(inode); sock = SOCKET_I(inode);
sk = sock->sk; sk = sock->sk;
sksec = sk->sk_security; sksec = sk->sk_security;
if (sksec->nlbl_state != NLBL_REQUIRE)
rcu_read_lock();
if (sksec->nlbl_state != NLBL_REQUIRE) {
rcu_read_unlock();
return 0; return 0;
}
local_bh_disable(); local_bh_disable();
bh_lock_sock_nested(sk); bh_lock_sock_nested(sk);
rc = selinux_netlbl_sock_setsid(sk, sksec->sid); if (likely(sksec->nlbl_state == NLBL_REQUIRE))
rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
else
rc = 0;
bh_unlock_sock(sk); bh_unlock_sock(sk);
local_bh_enable(); local_bh_enable();
rcu_read_unlock();
return rc; return rc;
} }
...@@ -385,7 +333,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, ...@@ -385,7 +333,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
struct sk_security_struct *sksec = sk->sk_security; struct sk_security_struct *sksec = sk->sk_security;
struct netlbl_lsm_secattr secattr; struct netlbl_lsm_secattr secattr;
rcu_read_lock();
if (level == IPPROTO_IP && optname == IP_OPTIONS && if (level == IPPROTO_IP && optname == IP_OPTIONS &&
sksec->nlbl_state == NLBL_LABELED) { sksec->nlbl_state == NLBL_LABELED) {
netlbl_secattr_init(&secattr); netlbl_secattr_init(&secattr);
...@@ -396,7 +343,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, ...@@ -396,7 +343,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
rc = -EACCES; rc = -EACCES;
netlbl_secattr_destroy(&secattr); netlbl_secattr_destroy(&secattr);
} }
rcu_read_unlock();
return rc; return rc;
} }
...@@ -89,7 +89,7 @@ static void selnl_notify(int msgtype, void *data) ...@@ -89,7 +89,7 @@ static void selnl_notify(int msgtype, void *data)
nlmsg_failure: nlmsg_failure:
kfree_skb(skb); kfree_skb(skb);
oom: oom:
printk(KERN_ERR "SELinux: OOM in %s\n", __FUNCTION__); printk(KERN_ERR "SELinux: OOM in %s\n", __func__);
goto out; goto out;
} }
......
/*
* Network port table
*
* SELinux must keep a mapping of network ports to labels/SIDs. This
* mapping is maintained as part of the normal policy but a fast cache is
* needed to reduce the lookup overhead.
*
* Author: Paul Moore <paul.moore@hp.com>
*
* This code is heavily based on the "netif" concept originally developed by
* James Morris <jmorris@redhat.com>
* (see security/selinux/netif.c for more information)
*
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2008
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/types.h>
#include <linux/rcupdate.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <asm/bug.h>
#include "netport.h"
#include "objsec.h"
#define SEL_NETPORT_HASH_SIZE 256
#define SEL_NETPORT_HASH_BKT_LIMIT 16
struct sel_netport_bkt {
int size;
struct list_head list;
};
struct sel_netport {
struct netport_security_struct psec;
struct list_head list;
struct rcu_head rcu;
};
/* NOTE: we are using a combined hash table for both IPv4 and IPv6, the reason
* for this is that I suspect most users will not make heavy use of both
* address families at the same time so one table will usually end up wasted,
* if this becomes a problem we can always add a hash table for each address
* family later */
static LIST_HEAD(sel_netport_list);
static DEFINE_SPINLOCK(sel_netport_lock);
static struct sel_netport_bkt sel_netport_hash[SEL_NETPORT_HASH_SIZE];
/**
* sel_netport_free - Frees a port entry
* @p: the entry's RCU field
*
* Description:
* This function is designed to be used as a callback to the call_rcu()
* function so that memory allocated to a hash table port entry can be
* released safely.
*
*/
static void sel_netport_free(struct rcu_head *p)
{
struct sel_netport *port = container_of(p, struct sel_netport, rcu);
kfree(port);
}
/**
* sel_netport_hashfn - Hashing function for the port table
* @pnum: port number
*
* Description:
* This is the hashing function for the port table, it returns the bucket
* number for the given port.
*
*/
static unsigned int sel_netport_hashfn(u16 pnum)
{
return (pnum & (SEL_NETPORT_HASH_SIZE - 1));
}
/**
* sel_netport_find - Search for a port record
* @protocol: protocol
* @port: pnum
*
* Description:
* Search the network port table and return the matching record. If an entry
* can not be found in the table return NULL.
*
*/
static struct sel_netport *sel_netport_find(u8 protocol, u16 pnum)
{
unsigned int idx;
struct sel_netport *port;
idx = sel_netport_hashfn(pnum);
list_for_each_entry_rcu(port, &sel_netport_hash[idx].list, list)
if (port->psec.port == pnum &&
port->psec.protocol == protocol)
return port;
return NULL;
}
/**
* sel_netport_insert - Insert a new port into the table
* @port: the new port record
*
* Description:
* Add a new port record to the network address hash table. Returns zero on
* success, negative values on failure.
*
*/
static int sel_netport_insert(struct sel_netport *port)
{
unsigned int idx;
/* we need to impose a limit on the growth of the hash table so check
* this bucket to make sure it is within the specified bounds */
idx = sel_netport_hashfn(port->psec.port);
list_add_rcu(&port->list, &sel_netport_hash[idx].list);
if (sel_netport_hash[idx].size == SEL_NETPORT_HASH_BKT_LIMIT) {
struct sel_netport *tail;
tail = list_entry(port->list.prev, struct sel_netport, list);
list_del_rcu(port->list.prev);
call_rcu(&tail->rcu, sel_netport_free);
} else
sel_netport_hash[idx].size++;
return 0;
}
/**
* sel_netport_sid_slow - Lookup the SID of a network address using the policy
* @protocol: protocol
* @pnum: port
* @sid: port SID
*
* Description:
* This function determines the SID of a network port by quering the security
* policy. The result is added to the network port table to speedup future
* queries. Returns zero on success, negative values on failure.
*
*/
static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid)
{
int ret;
struct sel_netport *port;
struct sel_netport *new = NULL;
spin_lock_bh(&sel_netport_lock);
port = sel_netport_find(protocol, pnum);
if (port != NULL) {
*sid = port->psec.sid;
ret = 0;
goto out;
}
new = kzalloc(sizeof(*new), GFP_ATOMIC);
if (new == NULL) {
ret = -ENOMEM;
goto out;
}
ret = security_port_sid(protocol, pnum, &new->psec.sid);
if (ret != 0)
goto out;
new->psec.port = pnum;
new->psec.protocol = protocol;
ret = sel_netport_insert(new);
if (ret != 0)
goto out;
*sid = new->psec.sid;
out:
spin_unlock_bh(&sel_netport_lock);
if (unlikely(ret)) {
printk(KERN_WARNING
"SELinux: failure in sel_netport_sid_slow(),"
" unable to determine network port label\n");
kfree(new);
}
return ret;
}
/**
* sel_netport_sid - Lookup the SID of a network port
* @protocol: protocol
* @pnum: port
* @sid: port SID
*
* Description:
* This function determines the SID of a network port using the fastest method
* possible. First the port table is queried, but if an entry can't be found
* then the policy is queried and the result is added to the table to speedup
* future queries. Returns zero on success, negative values on failure.
*
*/
int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid)
{
struct sel_netport *port;
rcu_read_lock();
port = sel_netport_find(protocol, pnum);
if (port != NULL) {
*sid = port->psec.sid;
rcu_read_unlock();
return 0;
}
rcu_read_unlock();
return sel_netport_sid_slow(protocol, pnum, sid);
}
/**
* sel_netport_flush - Flush the entire network port table
*
* Description:
* Remove all entries from the network address table.
*
*/
static void sel_netport_flush(void)
{
unsigned int idx;
struct sel_netport *port;
spin_lock_bh(&sel_netport_lock);
for (idx = 0; idx < SEL_NETPORT_HASH_SIZE; idx++) {
list_for_each_entry(port, &sel_netport_hash[idx].list, list) {
list_del_rcu(&port->list);
call_rcu(&port->rcu, sel_netport_free);
}
sel_netport_hash[idx].size = 0;
}
spin_unlock_bh(&sel_netport_lock);
}
static int sel_netport_avc_callback(u32 event, u32 ssid, u32 tsid,
u16 class, u32 perms, u32 *retained)
{
if (event == AVC_CALLBACK_RESET) {
sel_netport_flush();
synchronize_net();
}
return 0;
}
static __init int sel_netport_init(void)
{
int iter;
int ret;
if (!selinux_enabled)
return 0;
for (iter = 0; iter < SEL_NETPORT_HASH_SIZE; iter++) {
INIT_LIST_HEAD(&sel_netport_hash[iter].list);
sel_netport_hash[iter].size = 0;
}
ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET,
SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
if (ret != 0)
panic("avc_add_callback() failed, error %d\n", ret);
return ret;
}
__initcall(sel_netport_init);
...@@ -42,7 +42,8 @@ ...@@ -42,7 +42,8 @@
/* Policy capability filenames */ /* Policy capability filenames */
static char *policycap_names[] = { static char *policycap_names[] = {
"network_peer_controls" "network_peer_controls",
"open_perms"
}; };
unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
...@@ -391,7 +392,7 @@ static ssize_t sel_write_context(struct file * file, char *buf, size_t size) ...@@ -391,7 +392,7 @@ static ssize_t sel_write_context(struct file * file, char *buf, size_t size)
if (len > SIMPLE_TRANSACTION_LIMIT) { if (len > SIMPLE_TRANSACTION_LIMIT) {
printk(KERN_ERR "%s: context size (%u) exceeds payload " printk(KERN_ERR "%s: context size (%u) exceeds payload "
"max\n", __FUNCTION__, len); "max\n", __func__, len);
length = -ERANGE; length = -ERANGE;
goto out; goto out;
} }
...@@ -644,7 +645,7 @@ static ssize_t sel_write_create(struct file * file, char *buf, size_t size) ...@@ -644,7 +645,7 @@ static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
if (len > SIMPLE_TRANSACTION_LIMIT) { if (len > SIMPLE_TRANSACTION_LIMIT) {
printk(KERN_ERR "%s: context size (%u) exceeds payload " printk(KERN_ERR "%s: context size (%u) exceeds payload "
"max\n", __FUNCTION__, len); "max\n", __func__, len);
length = -ERANGE; length = -ERANGE;
goto out3; goto out3;
} }
...@@ -821,7 +822,7 @@ static ssize_t sel_write_member(struct file * file, char *buf, size_t size) ...@@ -821,7 +822,7 @@ static ssize_t sel_write_member(struct file * file, char *buf, size_t size)
if (len > SIMPLE_TRANSACTION_LIMIT) { if (len > SIMPLE_TRANSACTION_LIMIT) {
printk(KERN_ERR "%s: context size (%u) exceeds payload " printk(KERN_ERR "%s: context size (%u) exceeds payload "
"max\n", __FUNCTION__, len); "max\n", __func__, len);
length = -ERANGE; length = -ERANGE;
goto out3; goto out3;
} }
...@@ -1760,7 +1761,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) ...@@ -1760,7 +1761,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
out: out:
return ret; return ret;
err: err:
printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__); printk(KERN_ERR "%s: failed while creating inodes\n", __func__);
goto out; goto out;
} }
......
...@@ -280,8 +280,8 @@ int avtab_alloc(struct avtab *h, u32 nrules) ...@@ -280,8 +280,8 @@ int avtab_alloc(struct avtab *h, u32 nrules)
h->nel = 0; h->nel = 0;
h->nslot = nslot; h->nslot = nslot;
h->mask = mask; h->mask = mask;
printk(KERN_DEBUG "SELinux:%d avtab hash slots allocated. " printk(KERN_DEBUG "SELinux: %d avtab hash slots, %d rules.\n",
"Num of rules:%d\n", h->nslot, nrules); h->nslot, nrules);
return 0; return 0;
} }
...@@ -345,18 +345,18 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -345,18 +345,18 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
if (vers < POLICYDB_VERSION_AVTAB) { if (vers < POLICYDB_VERSION_AVTAB) {
rc = next_entry(buf32, fp, sizeof(u32)); rc = next_entry(buf32, fp, sizeof(u32));
if (rc < 0) { if (rc < 0) {
printk(KERN_ERR "security: avtab: truncated entry\n"); printk(KERN_ERR "SELinux: avtab: truncated entry\n");
return -1; return -1;
} }
items2 = le32_to_cpu(buf32[0]); items2 = le32_to_cpu(buf32[0]);
if (items2 > ARRAY_SIZE(buf32)) { if (items2 > ARRAY_SIZE(buf32)) {
printk(KERN_ERR "security: avtab: entry overflow\n"); printk(KERN_ERR "SELinux: avtab: entry overflow\n");
return -1; return -1;
} }
rc = next_entry(buf32, fp, sizeof(u32)*items2); rc = next_entry(buf32, fp, sizeof(u32)*items2);
if (rc < 0) { if (rc < 0) {
printk(KERN_ERR "security: avtab: truncated entry\n"); printk(KERN_ERR "SELinux: avtab: truncated entry\n");
return -1; return -1;
} }
items = 0; items = 0;
...@@ -364,19 +364,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -364,19 +364,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
val = le32_to_cpu(buf32[items++]); val = le32_to_cpu(buf32[items++]);
key.source_type = (u16)val; key.source_type = (u16)val;
if (key.source_type != val) { if (key.source_type != val) {
printk("security: avtab: truncated source type\n"); printk("SELinux: avtab: truncated source type\n");
return -1; return -1;
} }
val = le32_to_cpu(buf32[items++]); val = le32_to_cpu(buf32[items++]);
key.target_type = (u16)val; key.target_type = (u16)val;
if (key.target_type != val) { if (key.target_type != val) {
printk("security: avtab: truncated target type\n"); printk("SELinux: avtab: truncated target type\n");
return -1; return -1;
} }
val = le32_to_cpu(buf32[items++]); val = le32_to_cpu(buf32[items++]);
key.target_class = (u16)val; key.target_class = (u16)val;
if (key.target_class != val) { if (key.target_class != val) {
printk("security: avtab: truncated target class\n"); printk("SELinux: avtab: truncated target class\n");
return -1; return -1;
} }
...@@ -384,12 +384,12 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -384,12 +384,12 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
if (!(val & (AVTAB_AV | AVTAB_TYPE))) { if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
printk("security: avtab: null entry\n"); printk("SELinux: avtab: null entry\n");
return -1; return -1;
} }
if ((val & AVTAB_AV) && if ((val & AVTAB_AV) &&
(val & AVTAB_TYPE)) { (val & AVTAB_TYPE)) {
printk("security: avtab: entry has both access vectors and types\n"); printk("SELinux: avtab: entry has both access vectors and types\n");
return -1; return -1;
} }
...@@ -403,7 +403,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -403,7 +403,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
} }
if (items != items2) { if (items != items2) {
printk("security: avtab: entry only had %d items, expected %d\n", items2, items); printk("SELinux: avtab: entry only had %d items, expected %d\n", items2, items);
return -1; return -1;
} }
return 0; return 0;
...@@ -411,7 +411,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -411,7 +411,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
rc = next_entry(buf16, fp, sizeof(u16)*4); rc = next_entry(buf16, fp, sizeof(u16)*4);
if (rc < 0) { if (rc < 0) {
printk("security: avtab: truncated entry\n"); printk("SELinux: avtab: truncated entry\n");
return -1; return -1;
} }
...@@ -424,7 +424,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -424,7 +424,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
if (!policydb_type_isvalid(pol, key.source_type) || if (!policydb_type_isvalid(pol, key.source_type) ||
!policydb_type_isvalid(pol, key.target_type) || !policydb_type_isvalid(pol, key.target_type) ||
!policydb_class_isvalid(pol, key.target_class)) { !policydb_class_isvalid(pol, key.target_class)) {
printk(KERN_WARNING "security: avtab: invalid type or class\n"); printk(KERN_WARNING "SELinux: avtab: invalid type or class\n");
return -1; return -1;
} }
...@@ -435,19 +435,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -435,19 +435,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
} }
if (!set || set > 1) { if (!set || set > 1) {
printk(KERN_WARNING printk(KERN_WARNING
"security: avtab: more than one specifier\n"); "SELinux: avtab: more than one specifier\n");
return -1; return -1;
} }
rc = next_entry(buf32, fp, sizeof(u32)); rc = next_entry(buf32, fp, sizeof(u32));
if (rc < 0) { if (rc < 0) {
printk("security: avtab: truncated entry\n"); printk("SELinux: avtab: truncated entry\n");
return -1; return -1;
} }
datum.data = le32_to_cpu(*buf32); datum.data = le32_to_cpu(*buf32);
if ((key.specified & AVTAB_TYPE) && if ((key.specified & AVTAB_TYPE) &&
!policydb_type_isvalid(pol, datum.data)) { !policydb_type_isvalid(pol, datum.data)) {
printk(KERN_WARNING "security: avtab: invalid type\n"); printk(KERN_WARNING "SELinux: avtab: invalid type\n");
return -1; return -1;
} }
return insertf(a, &key, &datum, p); return insertf(a, &key, &datum, p);
...@@ -468,12 +468,12 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol) ...@@ -468,12 +468,12 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
rc = next_entry(buf, fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (rc < 0) { if (rc < 0) {
printk(KERN_ERR "security: avtab: truncated table\n"); printk(KERN_ERR "SELinux: avtab: truncated table\n");
goto bad; goto bad;
} }
nel = le32_to_cpu(buf[0]); nel = le32_to_cpu(buf[0]);
if (!nel) { if (!nel) {
printk(KERN_ERR "security: avtab: table is empty\n"); printk(KERN_ERR "SELinux: avtab: table is empty\n");
rc = -EINVAL; rc = -EINVAL;
goto bad; goto bad;
} }
...@@ -486,9 +486,9 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol) ...@@ -486,9 +486,9 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL); rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL);
if (rc) { if (rc) {
if (rc == -ENOMEM) if (rc == -ENOMEM)
printk(KERN_ERR "security: avtab: out of memory\n"); printk(KERN_ERR "SELinux: avtab: out of memory\n");
else if (rc == -EEXIST) else if (rc == -EEXIST)
printk(KERN_ERR "security: avtab: duplicate entry\n"); printk(KERN_ERR "SELinux: avtab: duplicate entry\n");
else else
rc = -EINVAL; rc = -EINVAL;
goto bad; goto bad;
......
...@@ -96,7 +96,7 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node) ...@@ -96,7 +96,7 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
if (new_state != node->cur_state) { if (new_state != node->cur_state) {
node->cur_state = new_state; node->cur_state = new_state;
if (new_state == -1) if (new_state == -1)
printk(KERN_ERR "security: expression result was undefined - disabling all rules.\n"); printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n");
/* turn the rules on or off */ /* turn the rules on or off */
for (cur = node->true_list; cur != NULL; cur = cur->next) { for (cur = node->true_list; cur != NULL; cur = cur->next) {
if (new_state <= 0) { if (new_state <= 0) {
...@@ -276,7 +276,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum ...@@ -276,7 +276,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
*/ */
if (k->specified & AVTAB_TYPE) { if (k->specified & AVTAB_TYPE) {
if (avtab_search(&p->te_avtab, k)) { if (avtab_search(&p->te_avtab, k)) {
printk("security: type rule already exists outside of a conditional."); printk("SELinux: type rule already exists outside of a conditional.");
goto err; goto err;
} }
/* /*
...@@ -291,7 +291,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum ...@@ -291,7 +291,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
node_ptr = avtab_search_node(&p->te_cond_avtab, k); node_ptr = avtab_search_node(&p->te_cond_avtab, k);
if (node_ptr) { if (node_ptr) {
if (avtab_search_node_next(node_ptr, k->specified)) { if (avtab_search_node_next(node_ptr, k->specified)) {
printk("security: too many conflicting type rules."); printk("SELinux: too many conflicting type rules.");
goto err; goto err;
} }
found = 0; found = 0;
...@@ -302,13 +302,13 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum ...@@ -302,13 +302,13 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
} }
} }
if (!found) { if (!found) {
printk("security: conflicting type rules.\n"); printk("SELinux: conflicting type rules.\n");
goto err; goto err;
} }
} }
} else { } else {
if (avtab_search(&p->te_cond_avtab, k)) { if (avtab_search(&p->te_cond_avtab, k)) {
printk("security: conflicting type rules when adding type rule for true.\n"); printk("SELinux: conflicting type rules when adding type rule for true.\n");
goto err; goto err;
} }
} }
...@@ -316,7 +316,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum ...@@ -316,7 +316,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
if (!node_ptr) { if (!node_ptr) {
printk("security: could not insert rule."); printk("SELinux: could not insert rule.");
goto err; goto err;
} }
...@@ -376,12 +376,12 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list * ...@@ -376,12 +376,12 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
static int expr_isvalid(struct policydb *p, struct cond_expr *expr) static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
{ {
if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
printk("security: conditional expressions uses unknown operator.\n"); printk("SELinux: conditional expressions uses unknown operator.\n");
return 0; return 0;
} }
if (expr->bool > p->p_bools.nprim) { if (expr->bool > p->p_bools.nprim) {
printk("security: conditional expressions uses unknown bool.\n"); printk("SELinux: conditional expressions uses unknown bool.\n");
return 0; return 0;
} }
return 1; return 1;
......
...@@ -364,7 +364,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) ...@@ -364,7 +364,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
count = le32_to_cpu(buf[2]); count = le32_to_cpu(buf[2]);
if (mapunit != sizeof(u64) * 8) { if (mapunit != sizeof(u64) * 8) {
printk(KERN_ERR "security: ebitmap: map size %u does not " printk(KERN_ERR "SELinux: ebitmap: map size %u does not "
"match my size %Zd (high bit was %d)\n", "match my size %Zd (high bit was %d)\n",
mapunit, sizeof(u64) * 8, e->highbit); mapunit, sizeof(u64) * 8, e->highbit);
goto bad; goto bad;
...@@ -382,19 +382,19 @@ int ebitmap_read(struct ebitmap *e, void *fp) ...@@ -382,19 +382,19 @@ int ebitmap_read(struct ebitmap *e, void *fp)
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
rc = next_entry(&startbit, fp, sizeof(u32)); rc = next_entry(&startbit, fp, sizeof(u32));
if (rc < 0) { if (rc < 0) {
printk(KERN_ERR "security: ebitmap: truncated map\n"); printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
goto bad; goto bad;
} }
startbit = le32_to_cpu(startbit); startbit = le32_to_cpu(startbit);
if (startbit & (mapunit - 1)) { if (startbit & (mapunit - 1)) {
printk(KERN_ERR "security: ebitmap start bit (%d) is " printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
"not a multiple of the map unit size (%u)\n", "not a multiple of the map unit size (%u)\n",
startbit, mapunit); startbit, mapunit);
goto bad; goto bad;
} }
if (startbit > e->highbit - mapunit) { if (startbit > e->highbit - mapunit) {
printk(KERN_ERR "security: ebitmap start bit (%d) is " printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
"beyond the end of the bitmap (%u)\n", "beyond the end of the bitmap (%u)\n",
startbit, (e->highbit - mapunit)); startbit, (e->highbit - mapunit));
goto bad; goto bad;
...@@ -405,7 +405,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) ...@@ -405,7 +405,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
if (!tmp) { if (!tmp) {
printk(KERN_ERR printk(KERN_ERR
"security: ebitmap: out of memory\n"); "SELinux: ebitmap: out of memory\n");
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
...@@ -418,7 +418,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) ...@@ -418,7 +418,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
} }
n = tmp; n = tmp;
} else if (startbit <= n->startbit) { } else if (startbit <= n->startbit) {
printk(KERN_ERR "security: ebitmap: start bit %d" printk(KERN_ERR "SELinux: ebitmap: start bit %d"
" comes after start bit %d\n", " comes after start bit %d\n",
startbit, n->startbit); startbit, n->startbit);
goto bad; goto bad;
...@@ -426,7 +426,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) ...@@ -426,7 +426,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
rc = next_entry(&map, fp, sizeof(u64)); rc = next_entry(&map, fp, sizeof(u64));
if (rc < 0) { if (rc < 0) {
printk(KERN_ERR "security: ebitmap: truncated map\n"); printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
goto bad; goto bad;
} }
map = le64_to_cpu(map); map = le64_to_cpu(map);
......
...@@ -111,6 +111,11 @@ static struct policydb_compat_info policydb_compat[] = { ...@@ -111,6 +111,11 @@ static struct policydb_compat_info policydb_compat[] = {
.version = POLICYDB_VERSION_POLCAP, .version = POLICYDB_VERSION_POLCAP,
.sym_num = SYM_NUM, .sym_num = SYM_NUM,
.ocon_num = OCON_NUM, .ocon_num = OCON_NUM,
},
{
.version = POLICYDB_VERSION_PERMISSIVE,
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
} }
}; };
...@@ -194,6 +199,7 @@ static int policydb_init(struct policydb *p) ...@@ -194,6 +199,7 @@ static int policydb_init(struct policydb *p)
goto out_free_symtab; goto out_free_symtab;
ebitmap_init(&p->policycaps); ebitmap_init(&p->policycaps);
ebitmap_init(&p->permissive_map);
out: out:
return rc; return rc;
...@@ -401,14 +407,14 @@ static int policydb_index_others(struct policydb *p) ...@@ -401,14 +407,14 @@ static int policydb_index_others(struct policydb *p)
{ {
int i, rc = 0; int i, rc = 0;
printk(KERN_DEBUG "security: %d users, %d roles, %d types, %d bools", printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools",
p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
if (selinux_mls_enabled) if (selinux_mls_enabled)
printk(", %d sens, %d cats", p->p_levels.nprim, printk(", %d sens, %d cats", p->p_levels.nprim,
p->p_cats.nprim); p->p_cats.nprim);
printk("\n"); printk("\n");
printk(KERN_DEBUG "security: %d classes, %d rules\n", printk(KERN_DEBUG "SELinux: %d classes, %d rules\n",
p->p_classes.nprim, p->te_avtab.nel); p->p_classes.nprim, p->te_avtab.nel);
#ifdef DEBUG_HASHES #ifdef DEBUG_HASHES
...@@ -687,6 +693,7 @@ void policydb_destroy(struct policydb *p) ...@@ -687,6 +693,7 @@ void policydb_destroy(struct policydb *p)
kfree(p->type_attr_map); kfree(p->type_attr_map);
kfree(p->undefined_perms); kfree(p->undefined_perms);
ebitmap_destroy(&p->policycaps); ebitmap_destroy(&p->policycaps);
ebitmap_destroy(&p->permissive_map);
return; return;
} }
...@@ -702,20 +709,20 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) ...@@ -702,20 +709,20 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s)
rc = sidtab_init(s); rc = sidtab_init(s);
if (rc) { if (rc) {
printk(KERN_ERR "security: out of memory on SID table init\n"); printk(KERN_ERR "SELinux: out of memory on SID table init\n");
goto out; goto out;
} }
head = p->ocontexts[OCON_ISID]; head = p->ocontexts[OCON_ISID];
for (c = head; c; c = c->next) { for (c = head; c; c = c->next) {
if (!c->context[0].user) { if (!c->context[0].user) {
printk(KERN_ERR "security: SID %s was never " printk(KERN_ERR "SELinux: SID %s was never "
"defined.\n", c->u.name); "defined.\n", c->u.name);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
if (sidtab_insert(s, c->sid[0], &c->context[0])) { if (sidtab_insert(s, c->sid[0], &c->context[0])) {
printk(KERN_ERR "security: unable to load initial " printk(KERN_ERR "SELinux: unable to load initial "
"SID %s.\n", c->u.name); "SID %s.\n", c->u.name);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
...@@ -809,13 +816,13 @@ static int mls_read_range_helper(struct mls_range *r, void *fp) ...@@ -809,13 +816,13 @@ static int mls_read_range_helper(struct mls_range *r, void *fp)
items = le32_to_cpu(buf[0]); items = le32_to_cpu(buf[0]);
if (items > ARRAY_SIZE(buf)) { if (items > ARRAY_SIZE(buf)) {
printk(KERN_ERR "security: mls: range overflow\n"); printk(KERN_ERR "SELinux: mls: range overflow\n");
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
rc = next_entry(buf, fp, sizeof(u32) * items); rc = next_entry(buf, fp, sizeof(u32) * items);
if (rc < 0) { if (rc < 0) {
printk(KERN_ERR "security: mls: truncated range\n"); printk(KERN_ERR "SELinux: mls: truncated range\n");
goto out; goto out;
} }
r->level[0].sens = le32_to_cpu(buf[0]); r->level[0].sens = le32_to_cpu(buf[0]);
...@@ -826,21 +833,21 @@ static int mls_read_range_helper(struct mls_range *r, void *fp) ...@@ -826,21 +833,21 @@ static int mls_read_range_helper(struct mls_range *r, void *fp)
rc = ebitmap_read(&r->level[0].cat, fp); rc = ebitmap_read(&r->level[0].cat, fp);
if (rc) { if (rc) {
printk(KERN_ERR "security: mls: error reading low " printk(KERN_ERR "SELinux: mls: error reading low "
"categories\n"); "categories\n");
goto out; goto out;
} }
if (items > 1) { if (items > 1) {
rc = ebitmap_read(&r->level[1].cat, fp); rc = ebitmap_read(&r->level[1].cat, fp);
if (rc) { if (rc) {
printk(KERN_ERR "security: mls: error reading high " printk(KERN_ERR "SELinux: mls: error reading high "
"categories\n"); "categories\n");
goto bad_high; goto bad_high;
} }
} else { } else {
rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat); rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
if (rc) { if (rc) {
printk(KERN_ERR "security: mls: out of memory\n"); printk(KERN_ERR "SELinux: mls: out of memory\n");
goto bad_high; goto bad_high;
} }
} }
...@@ -866,7 +873,7 @@ static int context_read_and_validate(struct context *c, ...@@ -866,7 +873,7 @@ static int context_read_and_validate(struct context *c,
rc = next_entry(buf, fp, sizeof buf); rc = next_entry(buf, fp, sizeof buf);
if (rc < 0) { if (rc < 0) {
printk(KERN_ERR "security: context truncated\n"); printk(KERN_ERR "SELinux: context truncated\n");
goto out; goto out;
} }
c->user = le32_to_cpu(buf[0]); c->user = le32_to_cpu(buf[0]);
...@@ -874,7 +881,7 @@ static int context_read_and_validate(struct context *c, ...@@ -874,7 +881,7 @@ static int context_read_and_validate(struct context *c,
c->type = le32_to_cpu(buf[2]); c->type = le32_to_cpu(buf[2]);
if (p->policyvers >= POLICYDB_VERSION_MLS) { if (p->policyvers >= POLICYDB_VERSION_MLS) {
if (mls_read_range_helper(&c->range, fp)) { if (mls_read_range_helper(&c->range, fp)) {
printk(KERN_ERR "security: error reading MLS range of " printk(KERN_ERR "SELinux: error reading MLS range of "
"context\n"); "context\n");
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
...@@ -882,7 +889,7 @@ static int context_read_and_validate(struct context *c, ...@@ -882,7 +889,7 @@ static int context_read_and_validate(struct context *c,
} }
if (!policydb_context_isvalid(p, c)) { if (!policydb_context_isvalid(p, c)) {
printk(KERN_ERR "security: invalid security context\n"); printk(KERN_ERR "SELinux: invalid security context\n");
context_destroy(c); context_destroy(c);
rc = -EINVAL; rc = -EINVAL;
} }
...@@ -1128,7 +1135,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -1128,7 +1135,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comdatum = hashtab_search(p->p_commons.table,
cladatum->comkey); cladatum->comkey);
if (!cladatum->comdatum) { if (!cladatum->comdatum) {
printk(KERN_ERR "security: unknown common %s\n", printk(KERN_ERR "SELinux: unknown common %s\n",
cladatum->comkey); cladatum->comkey);
rc = -EINVAL; rc = -EINVAL;
goto bad; goto bad;
...@@ -1283,13 +1290,13 @@ static int mls_read_level(struct mls_level *lp, void *fp) ...@@ -1283,13 +1290,13 @@ static int mls_read_level(struct mls_level *lp, void *fp)
rc = next_entry(buf, fp, sizeof buf); rc = next_entry(buf, fp, sizeof buf);
if (rc < 0) { if (rc < 0) {
printk(KERN_ERR "security: mls: truncated level\n"); printk(KERN_ERR "SELinux: mls: truncated level\n");
goto bad; goto bad;
} }
lp->sens = le32_to_cpu(buf[0]); lp->sens = le32_to_cpu(buf[0]);
if (ebitmap_read(&lp->cat, fp)) { if (ebitmap_read(&lp->cat, fp)) {
printk(KERN_ERR "security: mls: error reading level " printk(KERN_ERR "SELinux: mls: error reading level "
"categories\n"); "categories\n");
goto bad; goto bad;
} }
...@@ -1491,7 +1498,7 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1491,7 +1498,7 @@ int policydb_read(struct policydb *p, void *fp)
goto bad; goto bad;
if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) { if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
printk(KERN_ERR "security: policydb magic number 0x%x does " printk(KERN_ERR "SELinux: policydb magic number 0x%x does "
"not match expected magic number 0x%x\n", "not match expected magic number 0x%x\n",
le32_to_cpu(buf[0]), POLICYDB_MAGIC); le32_to_cpu(buf[0]), POLICYDB_MAGIC);
goto bad; goto bad;
...@@ -1499,27 +1506,27 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1499,27 +1506,27 @@ int policydb_read(struct policydb *p, void *fp)
len = le32_to_cpu(buf[1]); len = le32_to_cpu(buf[1]);
if (len != strlen(POLICYDB_STRING)) { if (len != strlen(POLICYDB_STRING)) {
printk(KERN_ERR "security: policydb string length %d does not " printk(KERN_ERR "SELinux: policydb string length %d does not "
"match expected length %Zu\n", "match expected length %Zu\n",
len, strlen(POLICYDB_STRING)); len, strlen(POLICYDB_STRING));
goto bad; goto bad;
} }
policydb_str = kmalloc(len + 1,GFP_KERNEL); policydb_str = kmalloc(len + 1,GFP_KERNEL);
if (!policydb_str) { if (!policydb_str) {
printk(KERN_ERR "security: unable to allocate memory for policydb " printk(KERN_ERR "SELinux: unable to allocate memory for policydb "
"string of length %d\n", len); "string of length %d\n", len);
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
rc = next_entry(policydb_str, fp, len); rc = next_entry(policydb_str, fp, len);
if (rc < 0) { if (rc < 0) {
printk(KERN_ERR "security: truncated policydb string identifier\n"); printk(KERN_ERR "SELinux: truncated policydb string identifier\n");
kfree(policydb_str); kfree(policydb_str);
goto bad; goto bad;
} }
policydb_str[len] = 0; policydb_str[len] = 0;
if (strcmp(policydb_str, POLICYDB_STRING)) { if (strcmp(policydb_str, POLICYDB_STRING)) {
printk(KERN_ERR "security: policydb string %s does not match " printk(KERN_ERR "SELinux: policydb string %s does not match "
"my string %s\n", policydb_str, POLICYDB_STRING); "my string %s\n", policydb_str, POLICYDB_STRING);
kfree(policydb_str); kfree(policydb_str);
goto bad; goto bad;
...@@ -1536,7 +1543,7 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1536,7 +1543,7 @@ int policydb_read(struct policydb *p, void *fp)
p->policyvers = le32_to_cpu(buf[0]); p->policyvers = le32_to_cpu(buf[0]);
if (p->policyvers < POLICYDB_VERSION_MIN || if (p->policyvers < POLICYDB_VERSION_MIN ||
p->policyvers > POLICYDB_VERSION_MAX) { p->policyvers > POLICYDB_VERSION_MAX) {
printk(KERN_ERR "security: policydb version %d does not match " printk(KERN_ERR "SELinux: policydb version %d does not match "
"my version range %d-%d\n", "my version range %d-%d\n",
le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
goto bad; goto bad;
...@@ -1570,16 +1577,20 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1570,16 +1577,20 @@ int policydb_read(struct policydb *p, void *fp)
ebitmap_read(&p->policycaps, fp) != 0) ebitmap_read(&p->policycaps, fp) != 0)
goto bad; goto bad;
if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
ebitmap_read(&p->permissive_map, fp) != 0)
goto bad;
info = policydb_lookup_compat(p->policyvers); info = policydb_lookup_compat(p->policyvers);
if (!info) { if (!info) {
printk(KERN_ERR "security: unable to find policy compat info " printk(KERN_ERR "SELinux: unable to find policy compat info "
"for version %d\n", p->policyvers); "for version %d\n", p->policyvers);
goto bad; goto bad;
} }
if (le32_to_cpu(buf[2]) != info->sym_num || if (le32_to_cpu(buf[2]) != info->sym_num ||
le32_to_cpu(buf[3]) != info->ocon_num) { le32_to_cpu(buf[3]) != info->ocon_num) {
printk(KERN_ERR "security: policydb table sizes (%d,%d) do " printk(KERN_ERR "SELinux: policydb table sizes (%d,%d) do "
"not match mine (%d,%d)\n", le32_to_cpu(buf[2]), "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
le32_to_cpu(buf[3]), le32_to_cpu(buf[3]),
info->sym_num, info->ocon_num); info->sym_num, info->ocon_num);
...@@ -1823,7 +1834,7 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1823,7 +1834,7 @@ int policydb_read(struct policydb *p, void *fp)
for (genfs_p = NULL, genfs = p->genfs; genfs; for (genfs_p = NULL, genfs = p->genfs; genfs;
genfs_p = genfs, genfs = genfs->next) { genfs_p = genfs, genfs = genfs->next) {
if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
printk(KERN_ERR "security: dup genfs " printk(KERN_ERR "SELinux: dup genfs "
"fstype %s\n", newgenfs->fstype); "fstype %s\n", newgenfs->fstype);
kfree(newgenfs->fstype); kfree(newgenfs->fstype);
kfree(newgenfs); kfree(newgenfs);
...@@ -1873,7 +1884,7 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1873,7 +1884,7 @@ int policydb_read(struct policydb *p, void *fp)
if (!strcmp(newc->u.name, c->u.name) && if (!strcmp(newc->u.name, c->u.name) &&
(!c->v.sclass || !newc->v.sclass || (!c->v.sclass || !newc->v.sclass ||
newc->v.sclass == c->v.sclass)) { newc->v.sclass == c->v.sclass)) {
printk(KERN_ERR "security: dup genfs " printk(KERN_ERR "SELinux: dup genfs "
"entry (%s,%s)\n", "entry (%s,%s)\n",
newgenfs->fstype, c->u.name); newgenfs->fstype, c->u.name);
goto bad_newc; goto bad_newc;
...@@ -1931,7 +1942,7 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1931,7 +1942,7 @@ int policydb_read(struct policydb *p, void *fp)
if (rc) if (rc)
goto bad; goto bad;
if (!mls_range_isvalid(p, &rt->target_range)) { if (!mls_range_isvalid(p, &rt->target_range)) {
printk(KERN_WARNING "security: rangetrans: invalid range\n"); printk(KERN_WARNING "SELinux: rangetrans: invalid range\n");
goto bad; goto bad;
} }
lrt = rt; lrt = rt;
......
...@@ -243,6 +243,8 @@ struct policydb { ...@@ -243,6 +243,8 @@ struct policydb {
struct ebitmap policycaps; struct ebitmap policycaps;
struct ebitmap permissive_map;
unsigned int policyvers; unsigned int policyvers;
unsigned int reject_unknown : 1; unsigned int reject_unknown : 1;
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/audit.h> #include <linux/audit.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/selinux.h>
#include <net/netlabel.h> #include <net/netlabel.h>
#include "flask.h" #include "flask.h"
...@@ -61,6 +62,7 @@ extern void selnl_notify_policyload(u32 seqno); ...@@ -61,6 +62,7 @@ extern void selnl_notify_policyload(u32 seqno);
unsigned int policydb_loaded_version; unsigned int policydb_loaded_version;
int selinux_policycap_netpeer; int selinux_policycap_netpeer;
int selinux_policycap_openperm;
/* /*
* This is declared in avc.c * This is declared in avc.c
...@@ -412,10 +414,35 @@ static int context_struct_compute_av(struct context *scontext, ...@@ -412,10 +414,35 @@ static int context_struct_compute_av(struct context *scontext,
return 0; return 0;
inval_class: inval_class:
printk(KERN_ERR "%s: unrecognized class %d\n", __FUNCTION__, tclass); printk(KERN_ERR "%s: unrecognized class %d\n", __func__, tclass);
return -EINVAL; return -EINVAL;
} }
/*
* Given a sid find if the type has the permissive flag set
*/
int security_permissive_sid(u32 sid)
{
struct context *context;
u32 type;
int rc;
POLICY_RDLOCK;
context = sidtab_search(&sidtab, sid);
BUG_ON(!context);
type = context->type;
/*
* we are intentionally using type here, not type-1, the 0th bit may
* someday indicate that we are globally setting permissive in policy.
*/
rc = ebitmap_get_bit(&policydb.permissive_map, type);
POLICY_RDUNLOCK;
return rc;
}
static int security_validtrans_handle_fail(struct context *ocontext, static int security_validtrans_handle_fail(struct context *ocontext,
struct context *ncontext, struct context *ncontext,
struct context *tcontext, struct context *tcontext,
...@@ -1096,7 +1123,7 @@ static int validate_classes(struct policydb *p) ...@@ -1096,7 +1123,7 @@ static int validate_classes(struct policydb *p)
continue; continue;
if (i > p->p_classes.nprim) { if (i > p->p_classes.nprim) {
printk(KERN_INFO printk(KERN_INFO
"security: class %s not defined in policy\n", "SELinux: class %s not defined in policy\n",
def_class); def_class);
if (p->reject_unknown) if (p->reject_unknown)
return -EINVAL; return -EINVAL;
...@@ -1107,7 +1134,7 @@ static int validate_classes(struct policydb *p) ...@@ -1107,7 +1134,7 @@ static int validate_classes(struct policydb *p)
pol_class = p->p_class_val_to_name[i-1]; pol_class = p->p_class_val_to_name[i-1];
if (strcmp(pol_class, def_class)) { if (strcmp(pol_class, def_class)) {
printk(KERN_ERR printk(KERN_ERR
"security: class %d is incorrect, found %s but should be %s\n", "SELinux: class %d is incorrect, found %s but should be %s\n",
i, pol_class, def_class); i, pol_class, def_class);
return -EINVAL; return -EINVAL;
} }
...@@ -1125,7 +1152,7 @@ static int validate_classes(struct policydb *p) ...@@ -1125,7 +1152,7 @@ static int validate_classes(struct policydb *p)
nprim = 1 << (perms->nprim - 1); nprim = 1 << (perms->nprim - 1);
if (perm_val > nprim) { if (perm_val > nprim) {
printk(KERN_INFO printk(KERN_INFO
"security: permission %s in class %s not defined in policy\n", "SELinux: permission %s in class %s not defined in policy\n",
def_perm, pol_class); def_perm, pol_class);
if (p->reject_unknown) if (p->reject_unknown)
return -EINVAL; return -EINVAL;
...@@ -1136,14 +1163,14 @@ static int validate_classes(struct policydb *p) ...@@ -1136,14 +1163,14 @@ static int validate_classes(struct policydb *p)
perdatum = hashtab_search(perms->table, def_perm); perdatum = hashtab_search(perms->table, def_perm);
if (perdatum == NULL) { if (perdatum == NULL) {
printk(KERN_ERR printk(KERN_ERR
"security: permission %s in class %s not found in policy, bad policy\n", "SELinux: permission %s in class %s not found in policy, bad policy\n",
def_perm, pol_class); def_perm, pol_class);
return -EINVAL; return -EINVAL;
} }
pol_val = 1 << (perdatum->value - 1); pol_val = 1 << (perdatum->value - 1);
if (pol_val != perm_val) { if (pol_val != perm_val) {
printk(KERN_ERR printk(KERN_ERR
"security: permission %s in class %s has incorrect value\n", "SELinux: permission %s in class %s has incorrect value\n",
def_perm, pol_class); def_perm, pol_class);
return -EINVAL; return -EINVAL;
} }
...@@ -1157,7 +1184,7 @@ static int validate_classes(struct policydb *p) ...@@ -1157,7 +1184,7 @@ static int validate_classes(struct policydb *p)
BUG_ON(!cladatum); BUG_ON(!cladatum);
if (!cladatum->comdatum) { if (!cladatum->comdatum) {
printk(KERN_ERR printk(KERN_ERR
"security: class %s should have an inherits clause but does not\n", "SELinux: class %s should have an inherits clause but does not\n",
pol_class); pol_class);
return -EINVAL; return -EINVAL;
} }
...@@ -1172,7 +1199,7 @@ static int validate_classes(struct policydb *p) ...@@ -1172,7 +1199,7 @@ static int validate_classes(struct policydb *p)
def_perm = kdefs->av_inherit[i].common_pts[j]; def_perm = kdefs->av_inherit[i].common_pts[j];
if (j >= perms->nprim) { if (j >= perms->nprim) {
printk(KERN_INFO printk(KERN_INFO
"security: permission %s in class %s not defined in policy\n", "SELinux: permission %s in class %s not defined in policy\n",
def_perm, pol_class); def_perm, pol_class);
if (p->reject_unknown) if (p->reject_unknown)
return -EINVAL; return -EINVAL;
...@@ -1183,13 +1210,13 @@ static int validate_classes(struct policydb *p) ...@@ -1183,13 +1210,13 @@ static int validate_classes(struct policydb *p)
perdatum = hashtab_search(perms->table, def_perm); perdatum = hashtab_search(perms->table, def_perm);
if (perdatum == NULL) { if (perdatum == NULL) {
printk(KERN_ERR printk(KERN_ERR
"security: permission %s in class %s not found in policy, bad policy\n", "SELinux: permission %s in class %s not found in policy, bad policy\n",
def_perm, pol_class); def_perm, pol_class);
return -EINVAL; return -EINVAL;
} }
if (perdatum->value != j + 1) { if (perdatum->value != j + 1) {
printk(KERN_ERR printk(KERN_ERR
"security: permission %s in class %s has incorrect value\n", "SELinux: permission %s in class %s has incorrect value\n",
def_perm, pol_class); def_perm, pol_class);
return -EINVAL; return -EINVAL;
} }
...@@ -1219,7 +1246,7 @@ static inline int convert_context_handle_invalid_context(struct context *context ...@@ -1219,7 +1246,7 @@ static inline int convert_context_handle_invalid_context(struct context *context
u32 len; u32 len;
context_struct_to_string(context, &s, &len); context_struct_to_string(context, &s, &len);
printk(KERN_ERR "security: context %s is invalid\n", s); printk(KERN_ERR "SELinux: context %s is invalid\n", s);
kfree(s); kfree(s);
} }
return rc; return rc;
...@@ -1299,7 +1326,7 @@ static int convert_context(u32 key, ...@@ -1299,7 +1326,7 @@ static int convert_context(u32 key,
bad: bad:
context_struct_to_string(&oldc, &s, &len); context_struct_to_string(&oldc, &s, &len);
context_destroy(&oldc); context_destroy(&oldc);
printk(KERN_ERR "security: invalidating context %s\n", s); printk(KERN_ERR "SELinux: invalidating context %s\n", s);
kfree(s); kfree(s);
goto out; goto out;
} }
...@@ -1308,6 +1335,8 @@ static void security_load_policycaps(void) ...@@ -1308,6 +1335,8 @@ static void security_load_policycaps(void)
{ {
selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps, selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
POLICYDB_CAPABILITY_NETPEER); POLICYDB_CAPABILITY_NETPEER);
selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
POLICYDB_CAPABILITY_OPENPERM);
} }
extern void selinux_complete_init(void); extern void selinux_complete_init(void);
...@@ -1350,7 +1379,7 @@ int security_load_policy(void *data, size_t len) ...@@ -1350,7 +1379,7 @@ int security_load_policy(void *data, size_t len)
/* Verify that the kernel defined classes are correct. */ /* Verify that the kernel defined classes are correct. */
if (validate_classes(&policydb)) { if (validate_classes(&policydb)) {
printk(KERN_ERR printk(KERN_ERR
"security: the definition of a class is incorrect\n"); "SELinux: the definition of a class is incorrect\n");
LOAD_UNLOCK; LOAD_UNLOCK;
sidtab_destroy(&sidtab); sidtab_destroy(&sidtab);
policydb_destroy(&policydb); policydb_destroy(&policydb);
...@@ -1384,14 +1413,14 @@ int security_load_policy(void *data, size_t len) ...@@ -1384,14 +1413,14 @@ int security_load_policy(void *data, size_t len)
/* Verify that the kernel defined classes are correct. */ /* Verify that the kernel defined classes are correct. */
if (validate_classes(&newpolicydb)) { if (validate_classes(&newpolicydb)) {
printk(KERN_ERR printk(KERN_ERR
"security: the definition of a class is incorrect\n"); "SELinux: the definition of a class is incorrect\n");
rc = -EINVAL; rc = -EINVAL;
goto err; goto err;
} }
rc = security_preserve_bools(&newpolicydb); rc = security_preserve_bools(&newpolicydb);
if (rc) { if (rc) {
printk(KERN_ERR "security: unable to preserve booleans\n"); printk(KERN_ERR "SELinux: unable to preserve booleans\n");
goto err; goto err;
} }
...@@ -1443,17 +1472,11 @@ int security_load_policy(void *data, size_t len) ...@@ -1443,17 +1472,11 @@ int security_load_policy(void *data, size_t len)
/** /**
* security_port_sid - Obtain the SID for a port. * security_port_sid - Obtain the SID for a port.
* @domain: communication domain aka address family
* @type: socket type
* @protocol: protocol number * @protocol: protocol number
* @port: port number * @port: port number
* @out_sid: security identifier * @out_sid: security identifier
*/ */
int security_port_sid(u16 domain, int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
u16 type,
u8 protocol,
u16 port,
u32 *out_sid)
{ {
struct ocontext *c; struct ocontext *c;
int rc = 0; int rc = 0;
...@@ -2203,7 +2226,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms) ...@@ -2203,7 +2226,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
match = hashtab_search(policydb.p_classes.table, class); match = hashtab_search(policydb.p_classes.table, class);
if (!match) { if (!match) {
printk(KERN_ERR "%s: unrecognized class %s\n", printk(KERN_ERR "%s: unrecognized class %s\n",
__FUNCTION__, class); __func__, class);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment