diff options
Diffstat (limited to 'security/smack/smack.h')
| -rw-r--r-- | security/smack/smack.h | 260 | 
1 files changed, 175 insertions, 85 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h index 43ae747a5aa..020307ef097 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -23,13 +23,52 @@  #include <linux/lsm_audit.h>  /* + * Smack labels were limited to 23 characters for a long time. + */ +#define SMK_LABELLEN	24 +#define SMK_LONGLABEL	256 + +/* + * This is the repository for labels seen so that it is + * not necessary to keep allocating tiny chuncks of memory + * and so that they can be shared. + * + * Labels are never modified in place. Anytime a label + * is imported (e.g. xattrset on a file) the list is checked + * for it and it is added if it doesn't exist. The address + * is passed out in either case. Entries are added, but + * never deleted. + * + * Since labels are hanging around anyway it doesn't + * hurt to maintain a secid for those awkward situations + * where kernel components that ought to use LSM independent + * interfaces don't. The secid should go away when all of + * these components have been repaired. + * + * The cipso value associated with the label gets stored here, too. + * + * Keep the access rules for this subject label here so that + * the entire set of rules does not need to be examined every + * time. + */ +struct smack_known { +	struct list_head		list; +	struct hlist_node		smk_hashed; +	char				*smk_known; +	u32				smk_secid; +	struct netlbl_lsm_secattr	smk_netlabel;	/* on wire labels */ +	struct list_head		smk_rules;	/* access rules */ +	struct mutex			smk_rules_lock;	/* lock for rules */ +}; + +/* + * Maximum number of bytes for the levels in a CIPSO IP option.   * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is   * bigger than can be used, and 24 is the next lower multiple   * of 8, and there are too many issues if there isn't space set   * aside for the terminating null byte.   */ -#define SMK_MAXLEN	23 -#define SMK_LABELLEN	(SMK_MAXLEN+1) +#define SMK_CIPSOLEN	24  struct superblock_smack {  	char		*smk_root; @@ -37,46 +76,47 @@ struct superblock_smack {  	char		*smk_hat;  	char		*smk_default;  	int		smk_initialized; -	spinlock_t	smk_sblock;	/* for initialization */  };  struct socket_smack { -	char		*smk_out;			/* outbound label */ -	char		*smk_in;			/* inbound label */ -	char		smk_packet[SMK_LABELLEN];	/* TCP peer label */ +	struct smack_known	*smk_out;	/* outbound label */ +	struct smack_known	*smk_in;	/* inbound label */ +	struct smack_known	*smk_packet;	/* TCP peer label */  };  /*   * Inode smack data   */  struct inode_smack { -	char		*smk_inode;	/* label of the fso */ -	struct mutex	smk_lock;	/* initialization lock */ -	int		smk_flags;	/* smack inode flags */ +	char			*smk_inode;	/* label of the fso */ +	struct smack_known	*smk_task;	/* label of the task */ +	struct smack_known	*smk_mmap;	/* label of the mmap domain */ +	struct mutex		smk_lock;	/* initialization lock */ +	int			smk_flags;	/* smack inode flags */ +}; + +struct task_smack { +	struct smack_known	*smk_task;	/* label for access control */ +	struct smack_known	*smk_forked;	/* label when forked */ +	struct list_head	smk_rules;	/* per task access rules */ +	struct mutex		smk_rules_lock;	/* lock for the rules */  };  #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */ +#define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */ +#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */  /*   * A label access rule.   */  struct smack_rule {  	struct list_head	list; -	char			*smk_subject; +	struct smack_known	*smk_subject;  	char			*smk_object;  	int			smk_access;  };  /* - * An entry in the table mapping smack values to - * CIPSO level/category-set values. - */ -struct smack_cipso { -	int	smk_level; -	char	smk_catset[SMK_LABELLEN]; -}; - -/*   * An entry in the table identifying hosts.   */  struct smk_netlbladdr { @@ -87,32 +127,14 @@ struct smk_netlbladdr {  };  /* - * This is the repository for labels seen so that it is - * not necessary to keep allocating tiny chuncks of memory - * and so that they can be shared. - * - * Labels are never modified in place. Anytime a label - * is imported (e.g. xattrset on a file) the list is checked - * for it and it is added if it doesn't exist. The address - * is passed out in either case. Entries are added, but - * never deleted. - * - * Since labels are hanging around anyway it doesn't - * hurt to maintain a secid for those awkward situations - * where kernel components that ought to use LSM independent - * interfaces don't. The secid should go away when all of - * these components have been repaired. - * - * If there is a cipso value associated with the label it - * gets stored here, too. This will most likely be rare as - * the cipso direct mapping in used internally. + * An entry in the table identifying ports.   */ -struct smack_known { +struct smk_port_label {  	struct list_head	list; -	char			smk_known[SMK_LABELLEN]; -	u32			smk_secid; -	struct smack_cipso	*smk_cipso; -	spinlock_t		smk_cipsolock; /* for changing cipso map */ +	struct sock		*smk_sock;	/* socket initialized on */ +	unsigned short		smk_port;	/* the port number */ +	struct smack_known	*smk_in;	/* inbound label */ +	struct smack_known	*smk_out;	/* outgoing label */  };  /* @@ -122,6 +144,7 @@ struct smack_known {  #define SMK_FSFLOOR	"smackfsfloor="  #define SMK_FSHAT	"smackfshat="  #define SMK_FSROOT	"smackfsroot=" +#define SMK_FSTRANS	"smackfstransmute="  #define SMACK_CIPSO_OPTION 	"-CIPSO" @@ -139,40 +162,56 @@ struct smack_known {  #define SMACK_CIPSO_SOCKET	1  /* - * smackfs magic number - * smackfs macic number + * CIPSO defaults. + */ +#define SMACK_CIPSO_DOI_DEFAULT		3	/* Historical */ +#define SMACK_CIPSO_DOI_INVALID		-1	/* Not a DOI */ +#define SMACK_CIPSO_DIRECT_DEFAULT	250	/* Arbitrary */ +#define SMACK_CIPSO_MAPPED_DEFAULT	251	/* Also arbitrary */ +#define SMACK_CIPSO_MAXLEVEL            255     /* CIPSO 2.2 standard */ +/* + * CIPSO 2.2 standard is 239, but Smack wants to use the + * categories in a structured way that limits the value to + * the bits in 23 bytes, hence the unusual number.   */ -#define SMACK_MAGIC	0x43415d53 /* "SMAC" */ +#define SMACK_CIPSO_MAXCATNUM           184     /* 23 * 8 */  /* - * A limit on the number of entries in the lists - * makes some of the list administration easier. + * Ptrace rules   */ -#define SMACK_LIST_MAX	10000 +#define SMACK_PTRACE_DEFAULT	0 +#define SMACK_PTRACE_EXACT	1 +#define SMACK_PTRACE_DRACONIAN	2 +#define SMACK_PTRACE_MAX	SMACK_PTRACE_DRACONIAN  /* - * CIPSO defaults. + * Flags for untraditional access modes. + * It shouldn't be necessary to avoid conflicts with definitions + * in fs.h, but do so anyway.   */ -#define SMACK_CIPSO_DOI_DEFAULT		3	/* Historical */ -#define SMACK_CIPSO_DOI_INVALID		-1	/* Not a DOI */ -#define SMACK_CIPSO_DIRECT_DEFAULT	250	/* Arbitrary */ -#define SMACK_CIPSO_MAXCATVAL		63	/* Bigger gets harder */ -#define SMACK_CIPSO_MAXLEVEL            255     /* CIPSO 2.2 standard */ -#define SMACK_CIPSO_MAXCATNUM           239     /* CIPSO 2.2 standard */ +#define MAY_TRANSMUTE	0x00001000	/* Controls directory labeling */ +#define MAY_LOCK	0x00002000	/* Locks should be writes, but ... */  /*   * Just to make the common cases easier to deal with   */ -#define MAY_ANY		(MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)  #define MAY_ANYREAD	(MAY_READ | MAY_EXEC) -#define MAY_ANYWRITE	(MAY_WRITE | MAY_APPEND)  #define MAY_READWRITE	(MAY_READ | MAY_WRITE)  #define MAY_NOT		0  /* - * Number of access types used by Smack (rwxa) + * Number of access types used by Smack (rwxatl)   */ -#define SMK_NUM_ACCESS_TYPE 4 +#define SMK_NUM_ACCESS_TYPE 6 + +/* SMACK data */ +struct smack_audit_data { +	const char *function; +	char *subject; +	char *object; +	char *request; +	int result; +};  /*   * Smack audit data; is empty if CONFIG_AUDIT not set @@ -181,6 +220,7 @@ struct smack_known {  struct smk_audit_info {  #ifdef CONFIG_AUDIT  	struct common_audit_data a; +	struct smack_audit_data sad;  #endif  };  /* @@ -191,22 +231,29 @@ struct inode_smack *new_inode_smack(char *);  /*   * These functions are in smack_access.c   */ -int smk_access(char *, char *, int, struct smk_audit_info *); +int smk_access_entry(char *, char *, struct list_head *); +int smk_access(struct smack_known *, char *, int, struct smk_audit_info *); +int smk_tskacc(struct task_smack *, char *, u32, struct smk_audit_info *);  int smk_curacc(char *, u32, struct smk_audit_info *); -int smack_to_cipso(const char *, struct smack_cipso *); -void smack_from_cipso(u32, char *, char *); -char *smack_from_secid(const u32); +struct smack_known *smack_from_secid(const u32); +char *smk_parse_smack(const char *string, int len); +int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);  char *smk_import(const char *, int);  struct smack_known *smk_import_entry(const char *, int); +void smk_insert_entry(struct smack_known *skp); +struct smack_known *smk_find_entry(const char *);  u32 smack_to_secid(const char *);  /*   * Shared data.   */  extern int smack_cipso_direct; -extern char *smack_net_ambient; -extern char *smack_onlycap; +extern int smack_cipso_mapped; +extern struct smack_known *smack_net_ambient; +extern struct smack_known *smack_onlycap; +extern struct smack_known *smack_syslog_label;  extern const char *smack_cipso_option; +extern int smack_ptrace_rule;  extern struct smack_known smack_known_floor;  extern struct smack_known smack_known_hat; @@ -215,22 +262,22 @@ extern struct smack_known smack_known_invalid;  extern struct smack_known smack_known_star;  extern struct smack_known smack_known_web; +extern struct mutex	smack_known_lock;  extern struct list_head smack_known_list; -extern struct list_head smack_rule_list;  extern struct list_head smk_netlbladdr_list;  extern struct security_operations smack_ops; +#define SMACK_HASH_SLOTS 16 +extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS]; +  /* - * Stricly for CIPSO level manipulation. - * Set the category bit number in a smack label sized buffer. + * Is the directory transmuting?   */ -static inline void smack_catset_bit(int cat, char *catsetp) +static inline int smk_inode_transmutable(const struct inode *isp)  { -	if (cat > SMK_LABELLEN * 8) -		return; - -	catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8); +	struct inode_smack *sip = isp->i_security; +	return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0;  }  /* @@ -243,6 +290,45 @@ static inline char *smk_of_inode(const struct inode *isp)  }  /* + * Present a pointer to the smack label entry in an task blob. + */ +static inline struct smack_known *smk_of_task(const struct task_smack *tsp) +{ +	return tsp->smk_task; +} + +/* + * Present a pointer to the forked smack label entry in an task blob. + */ +static inline struct smack_known *smk_of_forked(const struct task_smack *tsp) +{ +	return tsp->smk_forked; +} + +/* + * Present a pointer to the smack label in the current task blob. + */ +static inline struct smack_known *smk_of_current(void) +{ +	return smk_of_task(current_security()); +} + +/* + * Is the task privileged and allowed to be privileged + * by the onlycap rule. + */ +static inline int smack_privileged(int cap) +{ +	struct smack_known *skp = smk_of_current(); + +	if (!capable(cap)) +		return 0; +	if (smack_onlycap == NULL || smack_onlycap == skp) +		return 1; +	return 0; +} + +/*   * logging functions   */  #define SMACK_AUDIT_DENIED 0x1 @@ -263,9 +349,18 @@ void smack_log(char *subject_label, char *object_label,  static inline void smk_ad_init(struct smk_audit_info *a, const char *func,  			       char type)  { -	memset(a, 0, sizeof(*a)); +	memset(&a->sad, 0, sizeof(a->sad));  	a->a.type = type; -	a->a.smack_audit_data.function = func; +	a->a.smack_audit_data = &a->sad; +	a->a.smack_audit_data->function = func; +} + +static inline void smk_ad_init_net(struct smk_audit_info *a, const char *func, +				   char type, struct lsm_network_audit *net) +{ +	smk_ad_init(a, func, type); +	memset(net, 0, sizeof(*net)); +	a->a.u.net = net;  }  static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a, @@ -276,27 +371,22 @@ static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,  static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a,  						    struct dentry *d)  { -	a->a.u.fs.path.dentry = d; -} -static inline void smk_ad_setfield_u_fs_path_mnt(struct smk_audit_info *a, -						 struct vfsmount *m) -{ -	a->a.u.fs.path.mnt = m; +	a->a.u.dentry = d;  }  static inline void smk_ad_setfield_u_fs_inode(struct smk_audit_info *a,  					      struct inode *i)  { -	a->a.u.fs.inode = i; +	a->a.u.inode = i;  }  static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a,  					     struct path p)  { -	a->a.u.fs.path = p; +	a->a.u.path = p;  }  static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,  					    struct sock *sk)  { -	a->a.u.net.sk = sk; +	a->a.u.net->sk = sk;  }  #else /* no AUDIT */  | 
