diff -uprN -X lblnet-2.6_testing/Documentation/dontdiff lblnet-2.6_testing/include/net/netlabel.h lblnet-2.6-1011/include/net/netlabel.h --- lblnet-2.6_testing/include/net/netlabel.h 2008-10-07 10:56:35.000000000 -0700 +++ lblnet-2.6-1011/include/net/netlabel.h 2008-10-11 06:31:40.000000000 -0700 @@ -356,6 +356,19 @@ static inline void netlbl_secattr_free(s int netlbl_cfg_map_del(const char *domain, struct netlbl_audit *audit_info); int netlbl_cfg_unlbl_add_map(const char *domain, struct netlbl_audit *audit_info); +int netlbl_cfg_unlbl_add_fallback(struct net *net, + const char *dev_name, + const void *addr, + const void *mask, + u16 family, + u32 secid, + struct netlbl_audit *audit_info); +int netlbl_cfg_unlbl_del_fallback(struct net *net, + const char *dev_name, + const void *addr, + const void *mask, + u16 family, + struct netlbl_audit *audit_info); int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def, const char *domain, struct netlbl_audit *audit_info); @@ -412,6 +425,25 @@ static inline int netlbl_cfg_unlbl_add_m { return -ENOSYS; } +static inline int netlbl_cfg_unlbl_add_fallback(struct net *net, + const char *dev_name, + const void *addr, + const void *mask, + u16 family, + u32 secid, + struct netlbl_audit *audit_info) +{ + return -ENOSYS; +} +static inline int netlbl_cfg_unlbl_del_fallback(struct net *net, + const char *dev_name, + const void *addr, + const void *mask, + u16 family, + struct netlbl_audit *audit_info) +{ + return -ENOSYS; +} static inline int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def, const char *domain, struct netlbl_audit *audit_info) diff -uprN -X lblnet-2.6_testing/Documentation/dontdiff lblnet-2.6_testing/net/netlabel/netlabel_kapi.c lblnet-2.6-1011/net/netlabel/netlabel_kapi.c --- lblnet-2.6_testing/net/netlabel/netlabel_kapi.c 2008-10-07 10:56:46.000000000 -0700 +++ lblnet-2.6-1011/net/netlabel/netlabel_kapi.c 2008-10-11 06:31:40.000000000 -0700 @@ -103,6 +103,92 @@ cfg_unlbl_add_map_failure: return ret_val; } + +/** + * netlbl_cfg_unlbl_add_fallback - Adds a new fallback label + * @net: network namespace + * @dev_name: interface name + * @addr: IP address in network byte order (struct in[6]_addr) + * @mask: address mask in network byte order (struct in[6]_addr) + * @family: address family + * @secid: LSM secid value for the entry + * @audit_info: NetLabel audit information + * + * Description: + * Adds a new NetLabel static/fallback label to be used when protocol provided + * labels are not present on incoming traffic. If @dev_name is NULL then the + * default interface will be used. Returns zero on success, negative values on + * failure. + * + */ +int netlbl_cfg_unlbl_add_fallback(struct net *net, + const char *dev_name, + const void *addr, + const void *mask, + u16 family, + u32 secid, + struct netlbl_audit *audit_info) +{ + u32 addr_len; + + switch (family) { + case AF_INET: + addr_len = 4; + break; + case AF_INET6: + addr_len = 16; + break; + default: + return -EPFNOSUPPORT; + } + + return netlbl_unlhsh_add(net, + dev_name, addr, mask, addr_len, + secid, audit_info); +} + +/** + * netlbl_cfg_unlbl_del_fallback - Removes an existing fallback label + * @net: network namespace + * @dev_name: interface name + * @addr: IP address in network byte order (struct in[6]_addr) + * @mask: address mask in network byte order (struct in[6]_addr) + * @family: address family + * @secid: LSM secid value for the entry + * @audit_info: NetLabel audit information + * + * Description: + * Removes an existing NetLabel static/fallback label used when protocol + * provided labels are not present on incoming traffic. If @dev_name is NULL + * then the default interface will be used. Returns zero on success, negative + * values on failure. + * + */ +int netlbl_cfg_unlbl_del_fallback(struct net *net, + const char *dev_name, + const void *addr, + const void *mask, + u16 family, + struct netlbl_audit *audit_info) +{ + u32 addr_len; + + switch (family) { + case AF_INET: + addr_len = 4; + break; + case AF_INET6: + addr_len = 16; + break; + default: + return -EPFNOSUPPORT; + } + + return netlbl_unlhsh_remove(net, + dev_name, addr, mask, addr_len, + audit_info); +} + /** * netlbl_cfg_cipsov4_add_map - Add a new CIPSOv4 DOI definition and mapping * @doi_def: the DOI definition diff -uprN -X lblnet-2.6_testing/Documentation/dontdiff lblnet-2.6_testing/net/netlabel/netlabel_unlabeled.c lblnet-2.6-1011/net/netlabel/netlabel_unlabeled.c --- lblnet-2.6_testing/net/netlabel/netlabel_unlabeled.c 2008-10-07 10:56:46.000000000 -0700 +++ lblnet-2.6-1011/net/netlabel/netlabel_unlabeled.c 2008-10-11 06:31:40.000000000 -0700 @@ -450,13 +450,13 @@ add_iface_failure: * success, negative values on failure. * */ -static int netlbl_unlhsh_add(struct net *net, - const char *dev_name, - const void *addr, - const void *mask, - u32 addr_len, - u32 secid, - struct netlbl_audit *audit_info) +int netlbl_unlhsh_add(struct net *net, + const char *dev_name, + const void *addr, + const void *mask, + u32 addr_len, + u32 secid, + struct netlbl_audit *audit_info) { int ret_val; int ifindex; @@ -716,12 +716,12 @@ unlhsh_condremove_failure: * Returns zero on success, negative values on failure. * */ -static int netlbl_unlhsh_remove(struct net *net, - const char *dev_name, - const void *addr, - const void *mask, - u32 addr_len, - struct netlbl_audit *audit_info) +int netlbl_unlhsh_remove(struct net *net, + const char *dev_name, + const void *addr, + const void *mask, + u32 addr_len, + struct netlbl_audit *audit_info) { int ret_val; struct net_device *dev; diff -uprN -X lblnet-2.6_testing/Documentation/dontdiff lblnet-2.6_testing/net/netlabel/netlabel_unlabeled.h lblnet-2.6-1011/net/netlabel/netlabel_unlabeled.h --- lblnet-2.6_testing/net/netlabel/netlabel_unlabeled.h 2008-10-07 10:56:46.000000000 -0700 +++ lblnet-2.6-1011/net/netlabel/netlabel_unlabeled.h 2008-10-11 06:31:40.000000000 -0700 @@ -221,6 +221,21 @@ int netlbl_unlabel_genl_init(void); /* General Unlabeled init function */ int netlbl_unlabel_init(u32 size); +/* Static/Fallback label management functions */ +int netlbl_unlhsh_add(struct net *net, + const char *dev_name, + const void *addr, + const void *mask, + u32 addr_len, + u32 secid, + struct netlbl_audit *audit_info); +int netlbl_unlhsh_remove(struct net *net, + const char *dev_name, + const void *addr, + const void *mask, + u32 addr_len, + struct netlbl_audit *audit_info); + /* Process Unlabeled incoming network packets */ int netlbl_unlabel_getattr(const struct sk_buff *skb, u16 family, diff -uprN -X lblnet-2.6_testing/Documentation/dontdiff lblnet-2.6_testing/security/smack/smack_access.c lblnet-2.6-1011/security/smack/smack_access.c --- lblnet-2.6_testing/security/smack/smack_access.c 2008-10-07 10:56:47.000000000 -0700 +++ lblnet-2.6-1011/security/smack/smack_access.c 2008-10-11 06:31:40.000000000 -0700 @@ -57,7 +57,14 @@ struct smack_known smack_known_invalid = .smk_cipso = NULL, }; -struct smack_known *smack_known = &smack_known_invalid; +struct smack_known smack_known_internet = { + .smk_next = &smack_known_invalid, + .smk_known = "@", + .smk_secid = 7, + .smk_cipso = NULL, +}; + +struct smack_known *smack_known = &smack_known_internet; /* * The initial value needs to be bigger than any of the @@ -99,6 +106,16 @@ int smk_access(char *subject_label, char strcmp(subject_label, smack_known_star.smk_known) == 0) return -EACCES; /* + * An internet object can be accessed by any subject. + * Tasks cannot be assigned the internet label. + * An internet subject can access any object. + */ + if (object_label == smack_known_internet.smk_known || + subject_label == smack_known_internet.smk_known || + strcmp(object_label, smack_known_internet.smk_known) == 0 || + strcmp(subject_label, smack_known_internet.smk_known) == 0) + return 0; + /* * A star object can be accessed by any subject. */ if (object_label == smack_known_star.smk_known || diff -uprN -X lblnet-2.6_testing/Documentation/dontdiff lblnet-2.6_testing/security/smack/smackfs.c lblnet-2.6-1011/security/smack/smackfs.c --- lblnet-2.6_testing/security/smack/smackfs.c 2008-10-07 10:56:47.000000000 -0700 +++ lblnet-2.6-1011/security/smack/smackfs.c 2008-10-12 12:59:36.000000000 -0700 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,8 @@ enum smk_inos { SMK_DIRECT = 6, /* CIPSO level indicating direct label */ SMK_AMBIENT = 7, /* internet ambient label */ SMK_NLTYPE = 8, /* label scheme to use by default */ + SMK_ONLYCAP = 9, /* the only "capable" label */ + SMK_SLHOST = 10, /* single label hosts */ }; /* @@ -47,6 +50,7 @@ enum smk_inos { static DEFINE_MUTEX(smack_list_lock); static DEFINE_MUTEX(smack_cipso_lock); static DEFINE_MUTEX(smack_ambient_lock); +static DEFINE_MUTEX(smk_slhost_lock); /* * This is the "ambient" label for network traffic. @@ -68,6 +72,23 @@ int smack_net_nltype = NETLBL_NLTYPE_CIP */ int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; +/* + * Unless a process is running with this label even + * having CAP_MAC_OVERRIDE isn't enough to grant + * privilege to violate MAC policy. If no label is + * designated (the NULL case) capabilities apply to + * everyone. It is expected that the hat (^) label + * will be used if any label is used. + */ +char *smack_onlycap; + +/* + * Certain IP addresses may be designated as single label hosts. + * Packets are sent there unlabeled, but only from tasks that + * can write to the specified label. + */ +struct smk_slhost *smack_slhosts; + static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; struct smk_list_entry *smack_list; @@ -93,6 +114,13 @@ struct smk_list_entry *smack_list; #define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1) #define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) +/* + * Values for parsing single label host rules + * "1.2.3.4 X" + * "192.168.138.129 abcdefghijklmnopqrstuvw" + */ +#define SMK_SLHOSTMIN 9 +#define SMK_SLHOSTMAX 39 /* * Seq_file read operations for /smack/load @@ -580,6 +608,196 @@ static const struct file_operations smk_ .release = seq_release, }; +/* + * Seq_file read operations for /smack/slhost + */ + +static void *slhost_seq_start(struct seq_file *s, loff_t *pos) +{ + if (*pos == SEQ_READ_FINISHED) + return NULL; + + return smack_slhosts; +} + +static void *slhost_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + struct smk_slhost *skp = ((struct smk_slhost *) v)->smk_next; + + if (skp == NULL) + *pos = SEQ_READ_FINISHED; + + return skp; +} + +/* + * Print host/label pairs + */ +static int slhost_seq_show(struct seq_file *s, void *v) +{ + struct smk_slhost *skp = (struct smk_slhost *) v; + unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr; + + seq_printf(s, "%u.%u.%u.%u %s\n", hp[0], hp[1], hp[2], hp[3], + skp->smk_label); + + return 0; +} + +static void slhost_seq_stop(struct seq_file *s, void *v) +{ + /* No-op */ +} + +static struct seq_operations slhost_seq_ops = { + .start = slhost_seq_start, + .stop = slhost_seq_stop, + .next = slhost_seq_next, + .show = slhost_seq_show, +}; + +/** + * smk_open_slhost - open() for /smack/slhost + * @inode: inode structure representing file + * @file: "slhost" file pointer + * + * Connect our slhost_seq_* operations with /smack/slhost + * file_operations + */ +static int smk_open_slhost(struct inode *inode, struct file *file) +{ + return seq_open(file, &slhost_seq_ops); +} + +/** + * smk_write_slhost - write() for /smack/slhost + * @filp: file pointer, not actually used + * @buf: where to get the data from + * @count: bytes sent + * @ppos: where to start + * + * Accepts only one slhost per write call. + * Returns number of bytes written or error code, as appropriate + */ +static ssize_t smk_write_slhost(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct smk_slhost *skp; + struct sockaddr_in newname; + char smack[SMK_LABELLEN]; + char *sp; + char data[SMK_SLHOSTMAX]; + char *host = (char *)&newname.sin_addr.s_addr; + int rc; + int replace = 1; + struct netlbl_audit audit_info; + struct in_addr mask; + unsigned int m = 32; + __be32 bebits = 0x80000000; + __be32 nsa; + + /* + * Must have privilege. + * No partial writes. + * Enough data must be present. + * "