···315315Why: Deprecated by the new (standard) device driver binding model. Use316316 i2c_driver->probe() and ->remove() instead.317317Who: Jean Delvare <khali@linux-fr.org>318318+319319+---------------------------320320+321321+What: SELinux "compat_net" functionality322322+When: 2.6.30 at the earliest323323+Why: In 2.6.18 the Secmark concept was introduced to replace the "compat_net"324324+ network access control functionality of SELinux. Secmark offers both325325+ better performance and greater flexibility than the "compat_net"326326+ mechanism. Now that the major Linux distributions have moved to327327+ Secmark, it is time to deprecate the older mechanism and start the328328+ process of removing the old code.329329+Who: Paul Moore <paul.moore@hp.com>
+15-2
include/linux/capability.h
···529529 *530530 * Note that this does not set PF_SUPERPRIV on the task.531531 */532532-#define has_capability(t, cap) (security_capable((t), (cap)) == 0)533533-#define has_capability_noaudit(t, cap) (security_capable_noaudit((t), (cap)) == 0)532532+#define has_capability(t, cap) (security_real_capable((t), (cap)) == 0)533533+534534+/**535535+ * has_capability_noaudit - Determine if a task has a superior capability available (unaudited)536536+ * @t: The task in question537537+ * @cap: The capability to be tested for538538+ *539539+ * Return true if the specified task has the given superior capability540540+ * currently in effect, false if not, but don't write an audit message for the541541+ * check.542542+ *543543+ * Note that this does not set PF_SUPERPRIV on the task.544544+ */545545+#define has_capability_noaudit(t, cap) \546546+ (security_real_capable_noaudit((t), (cap)) == 0)534547535548extern int capable(int cap);536549
+32-9
include/linux/security.h
···4848 * These functions are in security/capability.c and are used4949 * as the default capabilities functions5050 */5151-extern int cap_capable(struct task_struct *tsk, int cap, int audit);5151+extern int cap_capable(struct task_struct *tsk, const struct cred *cred,5252+ int cap, int audit);5253extern int cap_settime(struct timespec *ts, struct timezone *tz);5354extern int cap_ptrace_may_access(struct task_struct *child, unsigned int mode);5455extern int cap_ptrace_traceme(struct task_struct *parent);···12521251 * @permitted contains the permitted capability set.12531252 * Return 0 and update @new if permission is granted.12541253 * @capable:12551255- * Check whether the @tsk process has the @cap capability.12541254+ * Check whether the @tsk process has the @cap capability in the indicated12551255+ * credentials.12561256 * @tsk contains the task_struct for the process.12571257+ * @cred contains the credentials to use.12571258 * @cap contains the capability <include/linux/capability.h>.12591259+ * @audit: Whether to write an audit message or not12581260 * Return 0 if the capability is granted for @tsk.12591261 * @acct:12601262 * Check permission before enabling or disabling process accounting. If···13501346 const kernel_cap_t *effective,13511347 const kernel_cap_t *inheritable,13521348 const kernel_cap_t *permitted);13531353- int (*capable) (struct task_struct *tsk, int cap, int audit);13491349+ int (*capable) (struct task_struct *tsk, const struct cred *cred,13501350+ int cap, int audit);13541351 int (*acct) (struct file *file);13551352 int (*sysctl) (struct ctl_table *table, int op);13561353 int (*quotactl) (int cmds, int type, int id, struct super_block *sb);···16331628 const kernel_cap_t *effective,16341629 const kernel_cap_t *inheritable,16351630 const kernel_cap_t *permitted);16361636-int security_capable(struct task_struct *tsk, int cap);16371637-int security_capable_noaudit(struct task_struct *tsk, int cap);16311631+int security_capable(int cap);16321632+int security_real_capable(struct task_struct *tsk, int cap);16331633+int security_real_capable_noaudit(struct task_struct *tsk, int cap);16381634int security_acct(struct file *file);16391635int security_sysctl(struct ctl_table *table, int op);16401636int security_quotactl(int cmds, int type, int id, struct super_block *sb);···18321826 return cap_capset(new, old, effective, inheritable, permitted);18331827}1834182818351835-static inline int security_capable(struct task_struct *tsk, int cap)18291829+static inline int security_capable(int cap)18361830{18371837- return cap_capable(tsk, cap, SECURITY_CAP_AUDIT);18311831+ return cap_capable(current, current_cred(), cap, SECURITY_CAP_AUDIT);18381832}1839183318401840-static inline int security_capable_noaudit(struct task_struct *tsk, int cap)18341834+static inline int security_real_capable(struct task_struct *tsk, int cap)18411835{18421842- return cap_capable(tsk, cap, SECURITY_CAP_NOAUDIT);18361836+ int ret;18371837+18381838+ rcu_read_lock();18391839+ ret = cap_capable(tsk, __task_cred(tsk), cap, SECURITY_CAP_AUDIT);18401840+ rcu_read_unlock();18411841+ return ret;18421842+}18431843+18441844+static inline18451845+int security_real_capable_noaudit(struct task_struct *tsk, int cap)18461846+{18471847+ int ret;18481848+18491849+ rcu_read_lock();18501850+ ret = cap_capable(tsk, __task_cred(tsk), cap,18511851+ SECURITY_CAP_NOAUDIT);18521852+ rcu_read_unlock();18531853+ return ret;18431854}1844185518451856static inline int security_acct(struct file *file)
···306306 BUG();307307 }308308309309- if (has_capability(current, cap)) {309309+ if (security_capable(cap) == 0) {310310 current->flags |= PF_SUPERPRIV;311311 return 1;312312 }
+65-21
net/ipv4/cipso_ipv4.c
···3838#include <linux/spinlock.h>3939#include <linux/string.h>4040#include <linux/jhash.h>4141+#include <linux/audit.h>4142#include <net/ip.h>4243#include <net/icmp.h>4344#include <net/tcp.h>···450449/**451450 * cipso_v4_doi_add - Add a new DOI to the CIPSO protocol engine452451 * @doi_def: the DOI structure452452+ * @audit_info: NetLabel audit information453453 *454454 * Description:455455 * The caller defines a new DOI for use by the CIPSO engine and calls this···460458 * zero on success and non-zero on failure.461459 *462460 */463463-int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)461461+int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,462462+ struct netlbl_audit *audit_info)464463{464464+ int ret_val = -EINVAL;465465 u32 iter;466466+ u32 doi;467467+ u32 doi_type;468468+ struct audit_buffer *audit_buf;469469+470470+ doi = doi_def->doi;471471+ doi_type = doi_def->type;466472467473 if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)468468- return -EINVAL;474474+ goto doi_add_return;469475 for (iter = 0; iter < CIPSO_V4_TAG_MAXCNT; iter++) {470476 switch (doi_def->tags[iter]) {471477 case CIPSO_V4_TAG_RBITMAP:472478 break;473479 case CIPSO_V4_TAG_RANGE:474474- if (doi_def->type != CIPSO_V4_MAP_PASS)475475- return -EINVAL;476476- break;477477- case CIPSO_V4_TAG_INVALID:478478- if (iter == 0)479479- return -EINVAL;480480- break;481480 case CIPSO_V4_TAG_ENUM:482481 if (doi_def->type != CIPSO_V4_MAP_PASS)483483- return -EINVAL;482482+ goto doi_add_return;484483 break;485484 case CIPSO_V4_TAG_LOCAL:486485 if (doi_def->type != CIPSO_V4_MAP_LOCAL)487487- return -EINVAL;486486+ goto doi_add_return;487487+ break;488488+ case CIPSO_V4_TAG_INVALID:489489+ if (iter == 0)490490+ goto doi_add_return;488491 break;489492 default:490490- return -EINVAL;493493+ goto doi_add_return;491494 }492495 }493496494497 atomic_set(&doi_def->refcount, 1);495498496499 spin_lock(&cipso_v4_doi_list_lock);497497- if (cipso_v4_doi_search(doi_def->doi) != NULL)498498- goto doi_add_failure;500500+ if (cipso_v4_doi_search(doi_def->doi) != NULL) {501501+ spin_unlock(&cipso_v4_doi_list_lock);502502+ ret_val = -EEXIST;503503+ goto doi_add_return;504504+ }499505 list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list);500506 spin_unlock(&cipso_v4_doi_list_lock);507507+ ret_val = 0;501508502502- return 0;509509+doi_add_return:510510+ audit_buf = netlbl_audit_start(AUDIT_MAC_CIPSOV4_ADD, audit_info);511511+ if (audit_buf != NULL) {512512+ const char *type_str;513513+ switch (doi_type) {514514+ case CIPSO_V4_MAP_TRANS:515515+ type_str = "trans";516516+ break;517517+ case CIPSO_V4_MAP_PASS:518518+ type_str = "pass";519519+ break;520520+ case CIPSO_V4_MAP_LOCAL:521521+ type_str = "local";522522+ break;523523+ default:524524+ type_str = "(unknown)";525525+ }526526+ audit_log_format(audit_buf,527527+ " cipso_doi=%u cipso_type=%s res=%u",528528+ doi, type_str, ret_val == 0 ? 1 : 0);529529+ audit_log_end(audit_buf);530530+ }503531504504-doi_add_failure:505505- spin_unlock(&cipso_v4_doi_list_lock);506506- return -EEXIST;532532+ return ret_val;507533}508534509535/**···589559 */590560int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info)591561{562562+ int ret_val;592563 struct cipso_v4_doi *doi_def;564564+ struct audit_buffer *audit_buf;593565594566 spin_lock(&cipso_v4_doi_list_lock);595567 doi_def = cipso_v4_doi_search(doi);596568 if (doi_def == NULL) {597569 spin_unlock(&cipso_v4_doi_list_lock);598598- return -ENOENT;570570+ ret_val = -ENOENT;571571+ goto doi_remove_return;599572 }600573 if (!atomic_dec_and_test(&doi_def->refcount)) {601574 spin_unlock(&cipso_v4_doi_list_lock);602602- return -EBUSY;575575+ ret_val = -EBUSY;576576+ goto doi_remove_return;603577 }604578 list_del_rcu(&doi_def->list);605579 spin_unlock(&cipso_v4_doi_list_lock);606580607581 cipso_v4_cache_invalidate();608582 call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu);583583+ ret_val = 0;609584610610- return 0;585585+doi_remove_return:586586+ audit_buf = netlbl_audit_start(AUDIT_MAC_CIPSOV4_DEL, audit_info);587587+ if (audit_buf != NULL) {588588+ audit_log_format(audit_buf,589589+ " cipso_doi=%u res=%u",590590+ doi, ret_val == 0 ? 1 : 0);591591+ audit_log_end(audit_buf);592592+ }593593+594594+ return ret_val;611595}612596613597/**
+18-43
net/netlabel/netlabel_cipso_v4.c
···130130/**131131 * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition132132 * @info: the Generic NETLINK info block133133+ * @audit_info: NetLabel audit information133134 *134135 * Description:135136 * Create a new CIPSO_V4_MAP_TRANS DOI definition based on the given ADD···138137 * non-zero on error.139138 *140139 */141141-static int netlbl_cipsov4_add_std(struct genl_info *info)140140+static int netlbl_cipsov4_add_std(struct genl_info *info,141141+ struct netlbl_audit *audit_info)142142{143143 int ret_val = -EINVAL;144144 struct cipso_v4_doi *doi_def = NULL;···318316 }319317 }320318321321- ret_val = cipso_v4_doi_add(doi_def);319319+ ret_val = cipso_v4_doi_add(doi_def, audit_info);322320 if (ret_val != 0)323321 goto add_std_failure;324322 return 0;···332330/**333331 * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition334332 * @info: the Generic NETLINK info block333333+ * @audit_info: NetLabel audit information335334 *336335 * Description:337336 * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message···340337 * error.341338 *342339 */343343-static int netlbl_cipsov4_add_pass(struct genl_info *info)340340+static int netlbl_cipsov4_add_pass(struct genl_info *info,341341+ struct netlbl_audit *audit_info)344342{345343 int ret_val;346344 struct cipso_v4_doi *doi_def = NULL;···358354 if (ret_val != 0)359355 goto add_pass_failure;360356361361- ret_val = cipso_v4_doi_add(doi_def);357357+ ret_val = cipso_v4_doi_add(doi_def, audit_info);362358 if (ret_val != 0)363359 goto add_pass_failure;364360 return 0;···371367/**372368 * netlbl_cipsov4_add_local - Adds a CIPSO V4 DOI definition373369 * @info: the Generic NETLINK info block370370+ * @audit_info: NetLabel audit information374371 *375372 * Description:376373 * Create a new CIPSO_V4_MAP_LOCAL DOI definition based on the given ADD···379374 * non-zero on error.380375 *381376 */382382-static int netlbl_cipsov4_add_local(struct genl_info *info)377377+static int netlbl_cipsov4_add_local(struct genl_info *info,378378+ struct netlbl_audit *audit_info)383379{384380 int ret_val;385381 struct cipso_v4_doi *doi_def = NULL;···397391 if (ret_val != 0)398392 goto add_local_failure;399393400400- ret_val = cipso_v4_doi_add(doi_def);394394+ ret_val = cipso_v4_doi_add(doi_def, audit_info);401395 if (ret_val != 0)402396 goto add_local_failure;403397 return 0;···421415422416{423417 int ret_val = -EINVAL;424424- u32 type;425425- u32 doi;426418 const char *type_str = "(unknown)";427427- struct audit_buffer *audit_buf;428419 struct netlbl_audit audit_info;429420430421 if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||431422 !info->attrs[NLBL_CIPSOV4_A_MTYPE])432423 return -EINVAL;433424434434- doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);435425 netlbl_netlink_auditinfo(skb, &audit_info);436436-437437- type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]);438438- switch (type) {426426+ switch (nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE])) {439427 case CIPSO_V4_MAP_TRANS:440428 type_str = "trans";441441- ret_val = netlbl_cipsov4_add_std(info);429429+ ret_val = netlbl_cipsov4_add_std(info, &audit_info);442430 break;443431 case CIPSO_V4_MAP_PASS:444432 type_str = "pass";445445- ret_val = netlbl_cipsov4_add_pass(info);433433+ ret_val = netlbl_cipsov4_add_pass(info, &audit_info);446434 break;447435 case CIPSO_V4_MAP_LOCAL:448436 type_str = "local";449449- ret_val = netlbl_cipsov4_add_local(info);437437+ ret_val = netlbl_cipsov4_add_local(info, &audit_info);450438 break;451439 }452440 if (ret_val == 0)453441 atomic_inc(&netlabel_mgmt_protocount);454454-455455- audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,456456- &audit_info);457457- if (audit_buf != NULL) {458458- audit_log_format(audit_buf,459459- " cipso_doi=%u cipso_type=%s res=%u",460460- doi,461461- type_str,462462- ret_val == 0 ? 1 : 0);463463- audit_log_end(audit_buf);464464- }465442466443 return ret_val;467444}···714725static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)715726{716727 int ret_val = -EINVAL;717717- u32 doi = 0;718728 struct netlbl_domhsh_walk_arg cb_arg;719719- struct audit_buffer *audit_buf;720729 struct netlbl_audit audit_info;721730 u32 skip_bkt = 0;722731 u32 skip_chain = 0;···722735 if (!info->attrs[NLBL_CIPSOV4_A_DOI])723736 return -EINVAL;724737725725- doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);726738 netlbl_netlink_auditinfo(skb, &audit_info);727727-728728- cb_arg.doi = doi;739739+ cb_arg.doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);729740 cb_arg.audit_info = &audit_info;730741 ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain,731742 netlbl_cipsov4_remove_cb, &cb_arg);732743 if (ret_val == 0 || ret_val == -ENOENT) {733733- ret_val = cipso_v4_doi_remove(doi, &audit_info);744744+ ret_val = cipso_v4_doi_remove(cb_arg.doi, &audit_info);734745 if (ret_val == 0)735746 atomic_dec(&netlabel_mgmt_protocount);736736- }737737-738738- audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL,739739- &audit_info);740740- if (audit_buf != NULL) {741741- audit_log_format(audit_buf,742742- " cipso_doi=%u res=%u",743743- doi,744744- ret_val == 0 ? 1 : 0);745745- audit_log_end(audit_buf);746747 }747748748749 return ret_val;
+67
net/netlabel/netlabel_domainhash.c
···483483}484484485485/**486486+ * netlbl_domhsh_remove_af4 - Removes an address selector entry487487+ * @domain: the domain488488+ * @addr: IPv4 address489489+ * @mask: IPv4 address mask490490+ * @audit_info: NetLabel audit information491491+ *492492+ * Description:493493+ * Removes an individual address selector from a domain mapping and potentially494494+ * the entire mapping if it is empty. Returns zero on success, negative values495495+ * on failure.496496+ *497497+ */498498+int netlbl_domhsh_remove_af4(const char *domain,499499+ const struct in_addr *addr,500500+ const struct in_addr *mask,501501+ struct netlbl_audit *audit_info)502502+{503503+ struct netlbl_dom_map *entry_map;504504+ struct netlbl_af4list *entry_addr;505505+ struct netlbl_af4list *iter4;506506+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)507507+ struct netlbl_af6list *iter6;508508+#endif /* IPv6 */509509+ struct netlbl_domaddr4_map *entry;510510+511511+ rcu_read_lock();512512+513513+ if (domain)514514+ entry_map = netlbl_domhsh_search(domain);515515+ else516516+ entry_map = netlbl_domhsh_search_def(domain);517517+ if (entry_map == NULL || entry_map->type != NETLBL_NLTYPE_ADDRSELECT)518518+ goto remove_af4_failure;519519+520520+ spin_lock(&netlbl_domhsh_lock);521521+ entry_addr = netlbl_af4list_remove(addr->s_addr, mask->s_addr,522522+ &entry_map->type_def.addrsel->list4);523523+ spin_unlock(&netlbl_domhsh_lock);524524+525525+ if (entry_addr == NULL)526526+ goto remove_af4_failure;527527+ netlbl_af4list_foreach_rcu(iter4, &entry_map->type_def.addrsel->list4)528528+ goto remove_af4_single_addr;529529+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)530530+ netlbl_af6list_foreach_rcu(iter6, &entry_map->type_def.addrsel->list6)531531+ goto remove_af4_single_addr;532532+#endif /* IPv6 */533533+ /* the domain mapping is empty so remove it from the mapping table */534534+ netlbl_domhsh_remove_entry(entry_map, audit_info);535535+536536+remove_af4_single_addr:537537+ rcu_read_unlock();538538+ /* yick, we can't use call_rcu here because we don't have a rcu head539539+ * pointer but hopefully this should be a rare case so the pause540540+ * shouldn't be a problem */541541+ synchronize_rcu();542542+ entry = netlbl_domhsh_addr4_entry(entry_addr);543543+ cipso_v4_doi_putdef(entry->type_def.cipsov4);544544+ kfree(entry);545545+ return 0;546546+547547+remove_af4_failure:548548+ rcu_read_unlock();549549+ return -ENOENT;550550+}551551+552552+/**486553 * netlbl_domhsh_remove - Removes an entry from the domain hash table487554 * @domain: the domain to remove488555 * @audit_info: NetLabel audit information
···4545/**4646 * cap_capable - Determine whether a task has a particular effective capability4747 * @tsk: The task to query4848+ * @cred: The credentials to use4849 * @cap: The capability to check for4950 * @audit: Whether to write an audit message or not5051 *5152 * Determine whether the nominated task has the specified capability amongst5253 * its effective set, returning 0 if it does, -ve if it does not.5354 *5454- * NOTE WELL: cap_capable() cannot be used like the kernel's capable()5555- * function. That is, it has the reverse semantics: cap_capable() returns 05656- * when a task has a capability, but the kernel's capable() returns 1 for this5757- * case.5555+ * NOTE WELL: cap_has_capability() cannot be used like the kernel's capable()5656+ * and has_capability() functions. That is, it has the reverse semantics:5757+ * cap_has_capability() returns 0 when a task has a capability, but the5858+ * kernel's capable() and has_capability() returns 1 for this case.5859 */5959-int cap_capable(struct task_struct *tsk, int cap, int audit)6060+int cap_capable(struct task_struct *tsk, const struct cred *cred, int cap,6161+ int audit)6062{6161- __u32 cap_raised;6262-6363- /* Derived from include/linux/sched.h:capable. */6464- rcu_read_lock();6565- cap_raised = cap_raised(__task_cred(tsk)->cap_effective, cap);6666- rcu_read_unlock();6767- return cap_raised ? 0 : -EPERM;6363+ return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM;6864}69657066/**···156160 /* they are so limited unless the current task has the CAP_SETPCAP157161 * capability158162 */159159- if (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0)163163+ if (cap_capable(current, current_cred(), CAP_SETPCAP,164164+ SECURITY_CAP_AUDIT) == 0)160165 return 0;161166#endif162167 return 1;···866869 & (new->securebits ^ arg2)) /*[1]*/867870 || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/868871 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/869869- || (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0) /*[4]*/872872+ || (cap_capable(current, current_cred(), CAP_SETPCAP,873873+ SECURITY_CAP_AUDIT) != 0) /*[4]*/870874 /*871875 * [1] no changing of bits that are locked872876 * [2] no unlocking of locks···948950{949951 int cap_sys_admin = 0;950952951951- if (cap_capable(current, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT) == 0)953953+ if (cap_capable(current, current_cred(), CAP_SYS_ADMIN,954954+ SECURITY_CAP_NOAUDIT) == 0)952955 cap_sys_admin = 1;953956 return __vm_enough_memory(mm, pages, cap_sys_admin);954957}
···154154 effective, inheritable, permitted);155155}156156157157-int security_capable(struct task_struct *tsk, int cap)157157+int security_capable(int cap)158158{159159- return security_ops->capable(tsk, cap, SECURITY_CAP_AUDIT);159159+ return security_ops->capable(current, current_cred(), cap,160160+ SECURITY_CAP_AUDIT);160161}161162162162-int security_capable_noaudit(struct task_struct *tsk, int cap)163163+int security_real_capable(struct task_struct *tsk, int cap)163164{164164- return security_ops->capable(tsk, cap, SECURITY_CAP_NOAUDIT);165165+ const struct cred *cred;166166+ int ret;167167+168168+ cred = get_task_cred(tsk);169169+ ret = security_ops->capable(tsk, cred, cap, SECURITY_CAP_AUDIT);170170+ put_cred(cred);171171+ return ret;172172+}173173+174174+int security_real_capable_noaudit(struct task_struct *tsk, int cap)175175+{176176+ const struct cred *cred;177177+ int ret;178178+179179+ cred = get_task_cred(tsk);180180+ ret = security_ops->capable(tsk, cred, cap, SECURITY_CAP_NOAUDIT);181181+ put_cred(cred);182182+ return ret;165183}166184167185int security_acct(struct file *file)
-27
security/selinux/Kconfig
···94949595 If you are unsure how to answer this question, answer 1.96969797-config SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT9898- bool "NSA SELinux enable new secmark network controls by default"9999- depends on SECURITY_SELINUX100100- default n101101- help102102- This option determines whether the new secmark-based network103103- controls will be enabled by default. If not, the old internal104104- per-packet controls will be enabled by default, preserving105105- old behavior.106106-107107- If you enable the new controls, you will need updated108108- SELinux userspace libraries, tools and policy. Typically,109109- your distribution will provide these and enable the new controls110110- in the kernel they also distribute.111111-112112- Note that this option can be overridden at boot with the113113- selinux_compat_net parameter, and after boot via114114- /selinux/compat_net. See Documentation/kernel-parameters.txt115115- for details on this parameter.116116-117117- If you enable the new network controls, you will likely118118- also require the SECMARK and CONNSECMARK targets, as119119- well as any conntrack helpers for protocols which you120120- wish to control.121121-122122- If you are unsure what to do here, select N.123123-12497config SECURITY_SELINUX_POLICYDB_VERSION_MAX12598 bool "NSA SELinux maximum supported policy format version"12699 depends on SECURITY_SELINUX
···2727 u32 user;2828 u32 role;2929 u32 type;3030+ u32 len; /* length of string in bytes */3031 struct mls_range range;3132 char *str; /* string representation if context cannot be mapped. */3232- u32 len; /* length of string in bytes */3333};34343535static inline void mls_context_init(struct context *c)
+29-2
security/smack/smack.h
···1616#include <linux/capability.h>1717#include <linux/spinlock.h>1818#include <linux/security.h>1919+#include <linux/in.h>1920#include <net/netlabel.h>20212122/*···4039struct socket_smack {4140 char *smk_out; /* outbound label */4241 char *smk_in; /* inbound label */4242+ int smk_labeled; /* label scheme */4343 char smk_packet[SMK_LABELLEN]; /* TCP peer label */4444};4545···7977struct smack_cipso {8078 int smk_level;8179 char smk_catset[SMK_LABELLEN];8080+};8181+8282+/*8383+ * An entry in the table identifying hosts.8484+ */8585+struct smk_netlbladdr {8686+ struct smk_netlbladdr *smk_next;8787+ struct sockaddr_in smk_host; /* network address */8888+ struct in_addr smk_mask; /* network mask */8989+ char *smk_label; /* label */8290};83918492/*···139127#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT140128141129/*130130+ * How communications on this socket are treated.131131+ * Usually it's determined by the underlying netlabel code132132+ * but there are certain cases, including single label hosts133133+ * and potentially single label interfaces for which the134134+ * treatment can not be known in advance.135135+ *136136+ * The possibility of additional labeling schemes being137137+ * introduced in the future exists as well.138138+ */139139+#define SMACK_UNLABELED_SOCKET 0140140+#define SMACK_CIPSO_SOCKET 1141141+142142+/*143143+ * smackfs magic number142144 * smackfs macic number143145 */144146#define SMACK_MAGIC 0x43415d53 /* "SMAC" */···167141 * CIPSO defaults.168142 */169143#define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */144144+#define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */170145#define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */171146#define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */172147#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */···203176 * Shared data.204177 */205178extern int smack_cipso_direct;206206-extern int smack_net_nltype;207179extern char *smack_net_ambient;208180extern char *smack_onlycap;209181···212186extern struct smack_known smack_known_huh;213187extern struct smack_known smack_known_invalid;214188extern struct smack_known smack_known_star;215215-extern struct smack_known smack_known_unset;189189+extern struct smack_known smack_known_web;216190217191extern struct smk_list_entry *smack_list;192192+extern struct smk_netlbladdr *smack_netlbladdrs;218193extern struct security_operations smack_ops;219194220195/*
+19-9
security/smack/smack_access.c
···1515#include <linux/sched.h>1616#include "smack.h"17171818-struct smack_known smack_known_unset = {1919- .smk_next = NULL,2020- .smk_known = "UNSET",2121- .smk_secid = 1,2222- .smk_cipso = NULL,2323-};2424-2518struct smack_known smack_known_huh = {2626- .smk_next = &smack_known_unset,1919+ .smk_next = NULL,2720 .smk_known = "?",2821 .smk_secid = 2,2922 .smk_cipso = NULL,···5057 .smk_cipso = NULL,5158};52595353-struct smack_known *smack_known = &smack_known_invalid;6060+struct smack_known smack_known_web = {6161+ .smk_next = &smack_known_invalid,6262+ .smk_known = "@",6363+ .smk_secid = 7,6464+ .smk_cipso = NULL,6565+};6666+6767+struct smack_known *smack_known = &smack_known_web;54685569/*5670 * The initial value needs to be bigger than any of the···9898 if (subject_label == smack_known_star.smk_known ||9999 strcmp(subject_label, smack_known_star.smk_known) == 0)100100 return -EACCES;101101+ /*102102+ * An internet object can be accessed by any subject.103103+ * Tasks cannot be assigned the internet label.104104+ * An internet subject can access any object.105105+ */106106+ if (object_label == smack_known_web.smk_known ||107107+ subject_label == smack_known_web.smk_known ||108108+ strcmp(object_label, smack_known_web.smk_known) == 0 ||109109+ strcmp(subject_label, smack_known_web.smk_known) == 0)110110+ return 0;101111 /*102112 * A star object can be accessed by any subject.103113 */
+256-56
security/smack/smack_lsm.c
···1277127712781278 ssp->smk_in = csp;12791279 ssp->smk_out = csp;12801280+ ssp->smk_labeled = SMACK_CIPSO_SOCKET;12801281 ssp->smk_packet[0] = '\0';1281128212821283 sk->sk_security = ssp;···13421341 struct smack_cipso cipso;13431342 int rc;1344134313451345- switch (smack_net_nltype) {13461346- case NETLBL_NLTYPE_CIPSOV4:13471347- nlsp->domain = smack;13481348- nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;13441344+ nlsp->domain = smack;13451345+ nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;1349134613501350- rc = smack_to_cipso(smack, &cipso);13511351- if (rc == 0) {13521352- nlsp->attr.mls.lvl = cipso.smk_level;13531353- smack_set_catset(cipso.smk_catset, nlsp);13541354- } else {13551355- nlsp->attr.mls.lvl = smack_cipso_direct;13561356- smack_set_catset(smack, nlsp);13571357- }13581358- break;13591359- default:13601360- break;13471347+ rc = smack_to_cipso(smack, &cipso);13481348+ if (rc == 0) {13491349+ nlsp->attr.mls.lvl = cipso.smk_level;13501350+ smack_set_catset(cipso.smk_catset, nlsp);13511351+ } else {13521352+ nlsp->attr.mls.lvl = smack_cipso_direct;13531353+ smack_set_catset(smack, nlsp);13611354 }13621355}1363135613641357/**13651358 * smack_netlabel - Set the secattr on a socket13661359 * @sk: the socket13601360+ * @labeled: socket label scheme13671361 *13681362 * Convert the outbound smack value (smk_out) to a13691363 * secattr and attach it to the socket.13701364 *13711365 * Returns 0 on success or an error code13721366 */13731373-static int smack_netlabel(struct sock *sk)13671367+static int smack_netlabel(struct sock *sk, int labeled)13741368{13751369 struct socket_smack *ssp;13761370 struct netlbl_lsm_secattr secattr;13771377- int rc;13711371+ int rc = 0;1378137213791373 ssp = sk->sk_security;13801380- netlbl_secattr_init(&secattr);13811381- smack_to_secattr(ssp->smk_out, &secattr);13821382- rc = netlbl_sock_setattr(sk, &secattr);13831383- netlbl_secattr_destroy(&secattr);13741374+ /*13751375+ * Usually the netlabel code will handle changing the13761376+ * packet labeling based on the label.13771377+ * The case of a single label host is different, because13781378+ * a single label host should never get a labeled packet13791379+ * even though the label is usually associated with a packet13801380+ * label.13811381+ */13821382+ local_bh_disable();13831383+ bh_lock_sock_nested(sk);13841384+13851385+ if (ssp->smk_out == smack_net_ambient ||13861386+ labeled == SMACK_UNLABELED_SOCKET)13871387+ netlbl_sock_delattr(sk);13881388+ else {13891389+ netlbl_secattr_init(&secattr);13901390+ smack_to_secattr(ssp->smk_out, &secattr);13911391+ rc = netlbl_sock_setattr(sk, &secattr);13921392+ netlbl_secattr_destroy(&secattr);13931393+ }13941394+13951395+ bh_unlock_sock(sk);13961396+ local_bh_enable();13971397+ /*13981398+ * Remember the label scheme used so that it is not13991399+ * necessary to do the netlabel setting if it has not14001400+ * changed the next time through.14011401+ *14021402+ * The -EDESTADDRREQ case is an indication that there's14031403+ * a single level host involved.14041404+ */14051405+ if (rc == 0)14061406+ ssp->smk_labeled = labeled;1384140713851408 return rc;13861409}···14571432 ssp->smk_in = sp;14581433 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {14591434 ssp->smk_out = sp;14601460- rc = smack_netlabel(sock->sk);14351435+ rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);14611436 if (rc != 0)14621437 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n",14631438 __func__, -rc);···14871462 /*14881463 * Set the outbound netlbl.14891464 */14901490- return smack_netlabel(sock->sk);14651465+ return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);14661466+}14671467+14681468+14691469+/**14701470+ * smack_host_label - check host based restrictions14711471+ * @sip: the object end14721472+ *14731473+ * looks for host based access restrictions14741474+ *14751475+ * This version will only be appropriate for really small14761476+ * sets of single label hosts. Because of the masking14771477+ * it cannot shortcut out on the first match. There are14781478+ * numerious ways to address the problem, but none of them14791479+ * have been applied here.14801480+ *14811481+ * Returns the label of the far end or NULL if it's not special.14821482+ */14831483+static char *smack_host_label(struct sockaddr_in *sip)14841484+{14851485+ struct smk_netlbladdr *snp;14861486+ char *bestlabel = NULL;14871487+ struct in_addr *siap = &sip->sin_addr;14881488+ struct in_addr *liap;14891489+ struct in_addr *miap;14901490+ struct in_addr bestmask;14911491+14921492+ if (siap->s_addr == 0)14931493+ return NULL;14941494+14951495+ bestmask.s_addr = 0;14961496+14971497+ for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {14981498+ liap = &snp->smk_host.sin_addr;14991499+ miap = &snp->smk_mask;15001500+ /*15011501+ * If the addresses match after applying the list entry mask15021502+ * the entry matches the address. If it doesn't move along to15031503+ * the next entry.15041504+ */15051505+ if ((liap->s_addr & miap->s_addr) !=15061506+ (siap->s_addr & miap->s_addr))15071507+ continue;15081508+ /*15091509+ * If the list entry mask identifies a single address15101510+ * it can't get any more specific.15111511+ */15121512+ if (miap->s_addr == 0xffffffff)15131513+ return snp->smk_label;15141514+ /*15151515+ * If the list entry mask is less specific than the best15161516+ * already found this entry is uninteresting.15171517+ */15181518+ if ((miap->s_addr | bestmask.s_addr) == bestmask.s_addr)15191519+ continue;15201520+ /*15211521+ * This is better than any entry found so far.15221522+ */15231523+ bestmask.s_addr = miap->s_addr;15241524+ bestlabel = snp->smk_label;15251525+ }15261526+15271527+ return bestlabel;15281528+}15291529+15301530+/**15311531+ * smack_socket_connect - connect access check15321532+ * @sock: the socket15331533+ * @sap: the other end15341534+ * @addrlen: size of sap15351535+ *15361536+ * Verifies that a connection may be possible15371537+ *15381538+ * Returns 0 on success, and error code otherwise15391539+ */15401540+static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,15411541+ int addrlen)15421542+{15431543+ struct socket_smack *ssp = sock->sk->sk_security;15441544+ char *hostsp;15451545+ int rc;15461546+15471547+ if (sock->sk == NULL || sock->sk->sk_family != PF_INET)15481548+ return 0;15491549+15501550+ if (addrlen < sizeof(struct sockaddr_in))15511551+ return -EINVAL;15521552+15531553+ hostsp = smack_host_label((struct sockaddr_in *)sap);15541554+ if (hostsp == NULL) {15551555+ if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)15561556+ return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);15571557+ return 0;15581558+ }15591559+15601560+ rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);15611561+ if (rc != 0)15621562+ return rc;15631563+15641564+ if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)15651565+ return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);15661566+ return 0;14911567}1492156814931569/**···22272101 if (newsmack == NULL)22282102 return -EINVAL;2229210321042104+ /*21052105+ * No process is ever allowed the web ("@") label.21062106+ */21072107+ if (newsmack == smack_known_web.smk_known)21082108+ return -EPERM;21092109+22302110 new = prepare_creds();22312231- if (!new)21112111+ if (new == NULL)22322112 return -ENOMEM;22332113 new->security = newsmack;22342114 commit_creds(new);···22762144}2277214522782146/**21472147+ * smack_socket_sendmsg - Smack check based on destination host21482148+ * @sock: the socket21492149+ * @msghdr: the message21502150+ * @size: the size of the message21512151+ *21522152+ * Return 0 if the current subject can write to the destination21532153+ * host. This is only a question if the destination is a single21542154+ * label host.21552155+ */21562156+static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,21572157+ int size)21582158+{21592159+ struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;21602160+ struct socket_smack *ssp = sock->sk->sk_security;21612161+ char *hostsp;21622162+ int rc;21632163+21642164+ /*21652165+ * Perfectly reasonable for this to be NULL21662166+ */21672167+ if (sip == NULL || sip->sin_family != PF_INET)21682168+ return 0;21692169+21702170+ hostsp = smack_host_label(sip);21712171+ if (hostsp == NULL) {21722172+ if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)21732173+ return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);21742174+ return 0;21752175+ }21762176+21772177+ rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);21782178+ if (rc != 0)21792179+ return rc;21802180+21812181+ if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)21822182+ return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);21832183+21842184+ return 0;21852185+21862186+}21872187+21882188+21892189+/**22792190 * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat22802191 * pair to smack22812192 * @sap: netlabel secattr···23292154static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip)23302155{23312156 char smack[SMK_LABELLEN];21572157+ char *sp;23322158 int pcat;2333215923342334- if ((sap->flags & NETLBL_SECATTR_MLS_LVL) == 0) {21602160+ if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {23352161 /*21622162+ * Looks like a CIPSO packet.23362163 * If there are flags but no level netlabel isn't23372164 * behaving the way we expect it to.23382165 *21662166+ * Get the categories, if any23392167 * Without guidance regarding the smack value23402168 * for the packet fall back on the network23412169 * ambient value.23422170 */23432343- strncpy(sip, smack_net_ambient, SMK_MAXLEN);23442344- return;23452345- }23462346- /*23472347- * Get the categories, if any23482348- */23492349- memset(smack, '\0', SMK_LABELLEN);23502350- if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0)23512351- for (pcat = -1;;) {23522352- pcat = netlbl_secattr_catmap_walk(sap->attr.mls.cat,23532353- pcat + 1);23542354- if (pcat < 0)23552355- break;23562356- smack_catset_bit(pcat, smack);21712171+ memset(smack, '\0', SMK_LABELLEN);21722172+ if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0)21732173+ for (pcat = -1;;) {21742174+ pcat = netlbl_secattr_catmap_walk(21752175+ sap->attr.mls.cat, pcat + 1);21762176+ if (pcat < 0)21772177+ break;21782178+ smack_catset_bit(pcat, smack);21792179+ }21802180+ /*21812181+ * If it is CIPSO using smack direct mapping21822182+ * we are already done. WeeHee.21832183+ */21842184+ if (sap->attr.mls.lvl == smack_cipso_direct) {21852185+ memcpy(sip, smack, SMK_MAXLEN);21862186+ return;23572187 }23582358- /*23592359- * If it is CIPSO using smack direct mapping23602360- * we are already done. WeeHee.23612361- */23622362- if (sap->attr.mls.lvl == smack_cipso_direct) {23632363- memcpy(sip, smack, SMK_MAXLEN);21882188+ /*21892189+ * Look it up in the supplied table if it is not21902190+ * a direct mapping.21912191+ */21922192+ smack_from_cipso(sap->attr.mls.lvl, smack, sip);21932193+ return;21942194+ }21952195+ if ((sap->flags & NETLBL_SECATTR_SECID) != 0) {21962196+ /*21972197+ * Looks like a fallback, which gives us a secid.21982198+ */21992199+ sp = smack_from_secid(sap->attr.secid);22002200+ /*22012201+ * This has got to be a bug because it is22022202+ * impossible to specify a fallback without22032203+ * specifying the label, which will ensure22042204+ * it has a secid, and the only way to get a22052205+ * secid is from a fallback.22062206+ */22072207+ BUG_ON(sp == NULL);22082208+ strncpy(sip, sp, SMK_MAXLEN);23642209 return;23652210 }23662211 /*23672367- * Look it up in the supplied table if it is not a direct mapping.22122212+ * Without guidance regarding the smack value22132213+ * for the packet fall back on the network22142214+ * ambient value.23682215 */23692369- smack_from_cipso(sap->attr.mls.lvl, smack, sip);22162216+ strncpy(sip, smack_net_ambient, SMK_MAXLEN);23702217 return;23712218}23722219···24042207 struct netlbl_lsm_secattr secattr;24052208 struct socket_smack *ssp = sk->sk_security;24062209 char smack[SMK_LABELLEN];22102210+ char *csp;24072211 int rc;2408221224092213 if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)···24132215 /*24142216 * Translate what netlabel gave us.24152217 */24162416- memset(smack, '\0', SMK_LABELLEN);24172218 netlbl_secattr_init(&secattr);22192219+24182220 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr);24192419- if (rc == 0)22212221+ if (rc == 0) {24202222 smack_from_secattr(&secattr, smack);24212421- else24222422- strncpy(smack, smack_net_ambient, SMK_MAXLEN);22232223+ csp = smack;22242224+ } else22252225+ csp = smack_net_ambient;22262226+24232227 netlbl_secattr_destroy(&secattr);22282228+24242229 /*24252230 * Receiving a packet requires that the other end24262231 * be able to write here. Read access is not required.24272232 * This is the simplist possible security model24282233 * for networking.24292234 */24302430- rc = smk_access(smack, ssp->smk_in, MAY_WRITE);22352235+ rc = smk_access(csp, ssp->smk_in, MAY_WRITE);24312236 if (rc != 0)24322237 netlbl_skbuff_err(skb, rc, 0);24332238 return rc;···24992298 /*25002299 * Translate what netlabel gave us.25012300 */25022502- memset(smack, '\0', SMK_LABELLEN);25032301 netlbl_secattr_init(&secattr);25042302 rc = netlbl_skbuff_getattr(skb, family, &secattr);25052303 if (rc == 0)···25412341 ssp->smk_in = ssp->smk_out = current_security();25422342 ssp->smk_packet[0] = '\0';2543234325442544- rc = smack_netlabel(sk);23442344+ rc = smack_netlabel(sk, SMACK_CIPSO_SOCKET);25452345 if (rc != 0)25462346 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n",25472347 __func__, -rc);···25672367 if (skb == NULL)25682368 return -EACCES;2569236925702570- memset(smack, '\0', SMK_LABELLEN);25712370 netlbl_secattr_init(&skb_secattr);25722371 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr);25732372 if (rc == 0)···29312732 .unix_may_send = smack_unix_may_send,2932273329332734 .socket_post_create = smack_socket_post_create,27352735+ .socket_connect = smack_socket_connect,27362736+ .socket_sendmsg = smack_socket_sendmsg,29342737 .socket_sock_rcv_skb = smack_socket_sock_rcv_skb,29352738 .socket_getpeersec_stream = smack_socket_getpeersec_stream,29362739 .socket_getpeersec_dgram = smack_socket_getpeersec_dgram,···29842783 /*29852784 * Initialize locks29862785 */29872987- spin_lock_init(&smack_known_unset.smk_cipsolock);29882786 spin_lock_init(&smack_known_huh.smk_cipsolock);29892787 spin_lock_init(&smack_known_hat.smk_cipsolock);29902788 spin_lock_init(&smack_known_star.smk_cipsolock);
+243-126
security/smack/smackfs.c
···2020#include <linux/vmalloc.h>2121#include <linux/security.h>2222#include <linux/mutex.h>2323+#include <net/net_namespace.h>2324#include <net/netlabel.h>2425#include <net/cipso_ipv4.h>2526#include <linux/seq_file.h>···3938 SMK_DOI = 5, /* CIPSO DOI */4039 SMK_DIRECT = 6, /* CIPSO level indicating direct label */4140 SMK_AMBIENT = 7, /* internet ambient label */4242- SMK_NLTYPE = 8, /* label scheme to use by default */4141+ SMK_NETLBLADDR = 8, /* single label hosts */4342 SMK_ONLYCAP = 9, /* the only "capable" label */4443};4544···4948static DEFINE_MUTEX(smack_list_lock);5049static DEFINE_MUTEX(smack_cipso_lock);5150static DEFINE_MUTEX(smack_ambient_lock);5151+static DEFINE_MUTEX(smk_netlbladdr_lock);52525353/*5454 * This is the "ambient" label for network traffic.···5755 * It can be reset via smackfs/ambient5856 */5957char *smack_net_ambient = smack_known_floor.smk_known;6060-6161-/*6262- * This is the default packet marking scheme for network traffic.6363- * It can be reset via smackfs/nltype6464- */6565-int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4;66586759/*6860 * This is the level in a CIPSO header that indicates a···7478 * will be used if any label is used.7579 */7680char *smack_onlycap;8181+8282+/*8383+ * Certain IP addresses may be designated as single label hosts.8484+ * Packets are sent there unlabeled, but only from tasks that8585+ * can write to the specified label.8686+ */8787+struct smk_netlbladdr *smack_netlbladdrs;77887889static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;7990struct smk_list_entry *smack_list;···107104#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)108105#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)109106107107+/**108108+ * smk_netlabel_audit_set - fill a netlbl_audit struct109109+ * @nap: structure to fill110110+ */111111+static void smk_netlabel_audit_set(struct netlbl_audit *nap)112112+{113113+ nap->loginuid = audit_get_loginuid(current);114114+ nap->sessionid = audit_get_sessionid(current);115115+ nap->secid = smack_to_secid(current_security());116116+}117117+118118+/*119119+ * Values for parsing single label host rules120120+ * "1.2.3.4 X"121121+ * "192.168.138.129/32 abcdefghijklmnopqrstuvw"122122+ */123123+#define SMK_NETLBLADDRMIN 9124124+#define SMK_NETLBLADDRMAX 42110125111126/*112127 * Seq_file read operations for /smack/load···365344{366345 int rc;367346 struct cipso_v4_doi *doip;368368- struct netlbl_audit audit_info;347347+ struct netlbl_audit nai;369348370370- audit_info.loginuid = audit_get_loginuid(current);371371- audit_info.sessionid = audit_get_sessionid(current);372372- audit_info.secid = smack_to_secid(current_security());349349+ smk_netlabel_audit_set(&nai);373350374374- rc = netlbl_cfg_map_del(NULL, &audit_info);351351+ rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);375352 if (rc != 0)376353 printk(KERN_WARNING "%s:%d remove rc = %d\n",377354 __func__, __LINE__, rc);···384365 for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)385366 doip->tags[rc] = CIPSO_V4_TAG_INVALID;386367387387- rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info);368368+ rc = netlbl_cfg_cipsov4_add(doip, &nai);388369 if (rc != 0) {389389- printk(KERN_WARNING "%s:%d add rc = %d\n",370370+ printk(KERN_WARNING "%s:%d cipso add rc = %d\n",390371 __func__, __LINE__, rc);391372 kfree(doip);373373+ return;374374+ }375375+ rc = netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai);376376+ if (rc != 0) {377377+ printk(KERN_WARNING "%s:%d map add rc = %d\n",378378+ __func__, __LINE__, rc);379379+ kfree(doip);380380+ return;392381 }393382}394383···406379static void smk_unlbl_ambient(char *oldambient)407380{408381 int rc;409409- struct netlbl_audit audit_info;382382+ struct netlbl_audit nai;410383411411- audit_info.loginuid = audit_get_loginuid(current);412412- audit_info.sessionid = audit_get_sessionid(current);413413- audit_info.secid = smack_to_secid(current_security());384384+ smk_netlabel_audit_set(&nai);414385415386 if (oldambient != NULL) {416416- rc = netlbl_cfg_map_del(oldambient, &audit_info);387387+ rc = netlbl_cfg_map_del(oldambient, PF_INET, NULL, NULL, &nai);417388 if (rc != 0)418389 printk(KERN_WARNING "%s:%d remove rc = %d\n",419390 __func__, __LINE__, rc);420391 }421392422422- rc = netlbl_cfg_unlbl_add_map(smack_net_ambient, &audit_info);393393+ rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET,394394+ NULL, NULL, &nai);423395 if (rc != 0)424396 printk(KERN_WARNING "%s:%d add rc = %d\n",425397 __func__, __LINE__, rc);···626600 .read = seq_read,627601 .llseek = seq_lseek,628602 .write = smk_write_cipso,603603+ .release = seq_release,604604+};605605+606606+/*607607+ * Seq_file read operations for /smack/netlabel608608+ */609609+610610+static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)611611+{612612+ if (*pos == SEQ_READ_FINISHED)613613+ return NULL;614614+615615+ return smack_netlbladdrs;616616+}617617+618618+static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)619619+{620620+ struct smk_netlbladdr *skp = ((struct smk_netlbladdr *) v)->smk_next;621621+622622+ if (skp == NULL)623623+ *pos = SEQ_READ_FINISHED;624624+625625+ return skp;626626+}627627+/*628628+#define BEMASK 0x80000000629629+*/630630+#define BEMASK 0x00000001631631+#define BEBITS (sizeof(__be32) * 8)632632+633633+/*634634+ * Print host/label pairs635635+ */636636+static int netlbladdr_seq_show(struct seq_file *s, void *v)637637+{638638+ struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v;639639+ unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;640640+ __be32 bebits;641641+ int maskn = 0;642642+643643+ for (bebits = BEMASK; bebits != 0; maskn++, bebits <<= 1)644644+ if ((skp->smk_mask.s_addr & bebits) == 0)645645+ break;646646+647647+ seq_printf(s, "%u.%u.%u.%u/%d %s\n",648648+ hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);649649+650650+ return 0;651651+}652652+653653+static void netlbladdr_seq_stop(struct seq_file *s, void *v)654654+{655655+ /* No-op */656656+}657657+658658+static struct seq_operations netlbladdr_seq_ops = {659659+ .start = netlbladdr_seq_start,660660+ .stop = netlbladdr_seq_stop,661661+ .next = netlbladdr_seq_next,662662+ .show = netlbladdr_seq_show,663663+};664664+665665+/**666666+ * smk_open_netlbladdr - open() for /smack/netlabel667667+ * @inode: inode structure representing file668668+ * @file: "netlabel" file pointer669669+ *670670+ * Connect our netlbladdr_seq_* operations with /smack/netlabel671671+ * file_operations672672+ */673673+static int smk_open_netlbladdr(struct inode *inode, struct file *file)674674+{675675+ return seq_open(file, &netlbladdr_seq_ops);676676+}677677+678678+/**679679+ * smk_write_netlbladdr - write() for /smack/netlabel680680+ * @filp: file pointer, not actually used681681+ * @buf: where to get the data from682682+ * @count: bytes sent683683+ * @ppos: where to start684684+ *685685+ * Accepts only one netlbladdr per write call.686686+ * Returns number of bytes written or error code, as appropriate687687+ */688688+static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,689689+ size_t count, loff_t *ppos)690690+{691691+ struct smk_netlbladdr *skp;692692+ struct sockaddr_in newname;693693+ char smack[SMK_LABELLEN];694694+ char *sp;695695+ char data[SMK_NETLBLADDRMAX];696696+ char *host = (char *)&newname.sin_addr.s_addr;697697+ int rc;698698+ struct netlbl_audit audit_info;699699+ struct in_addr mask;700700+ unsigned int m;701701+ __be32 bebits = BEMASK;702702+ __be32 nsa;703703+704704+ /*705705+ * Must have privilege.706706+ * No partial writes.707707+ * Enough data must be present.708708+ * "<addr/mask, as a.b.c.d/e><space><label>"709709+ * "<addr, as a.b.c.d><space><label>"710710+ */711711+ if (!capable(CAP_MAC_ADMIN))712712+ return -EPERM;713713+ if (*ppos != 0)714714+ return -EINVAL;715715+ if (count < SMK_NETLBLADDRMIN || count > SMK_NETLBLADDRMAX)716716+ return -EINVAL;717717+ if (copy_from_user(data, buf, count) != 0)718718+ return -EFAULT;719719+720720+ data[count] = '\0';721721+722722+ rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%d %s",723723+ &host[0], &host[1], &host[2], &host[3], &m, smack);724724+ if (rc != 6) {725725+ rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",726726+ &host[0], &host[1], &host[2], &host[3], smack);727727+ if (rc != 5)728728+ return -EINVAL;729729+ m = BEBITS;730730+ }731731+ if (m > BEBITS)732732+ return -EINVAL;733733+734734+ sp = smk_import(smack, 0);735735+ if (sp == NULL)736736+ return -EINVAL;737737+738738+ for (mask.s_addr = 0; m > 0; m--) {739739+ mask.s_addr |= bebits;740740+ bebits <<= 1;741741+ }742742+ /*743743+ * Only allow one writer at a time. Writes should be744744+ * quite rare and small in any case.745745+ */746746+ mutex_lock(&smk_netlbladdr_lock);747747+748748+ nsa = newname.sin_addr.s_addr;749749+ for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next)750750+ if (skp->smk_host.sin_addr.s_addr == nsa &&751751+ skp->smk_mask.s_addr == mask.s_addr)752752+ break;753753+754754+ smk_netlabel_audit_set(&audit_info);755755+756756+ if (skp == NULL) {757757+ skp = kzalloc(sizeof(*skp), GFP_KERNEL);758758+ if (skp == NULL)759759+ rc = -ENOMEM;760760+ else {761761+ rc = 0;762762+ skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;763763+ skp->smk_mask.s_addr = mask.s_addr;764764+ skp->smk_next = smack_netlbladdrs;765765+ skp->smk_label = sp;766766+ smack_netlbladdrs = skp;767767+ }768768+ } else {769769+ rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,770770+ &skp->smk_host.sin_addr, &skp->smk_mask,771771+ PF_INET, &audit_info);772772+ skp->smk_label = sp;773773+ }774774+775775+ /*776776+ * Now tell netlabel about the single label nature of777777+ * this host so that incoming packets get labeled.778778+ */779779+780780+ if (rc == 0)781781+ rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,782782+ &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,783783+ smack_to_secid(skp->smk_label), &audit_info);784784+785785+ if (rc == 0)786786+ rc = count;787787+788788+ mutex_unlock(&smk_netlbladdr_lock);789789+790790+ return rc;791791+}792792+793793+static const struct file_operations smk_netlbladdr_ops = {794794+ .open = smk_open_netlbladdr,795795+ .read = seq_read,796796+ .llseek = seq_lseek,797797+ .write = smk_write_netlbladdr,629798 .release = seq_release,630799};631800···1112891 .write = smk_write_onlycap,1113892};111489311151115-struct option_names {11161116- int o_number;11171117- char *o_name;11181118- char *o_alias;11191119-};11201120-11211121-static struct option_names netlbl_choices[] = {11221122- { NETLBL_NLTYPE_RIPSO,11231123- NETLBL_NLTYPE_RIPSO_NAME, "ripso" },11241124- { NETLBL_NLTYPE_CIPSOV4,11251125- NETLBL_NLTYPE_CIPSOV4_NAME, "cipsov4" },11261126- { NETLBL_NLTYPE_CIPSOV4,11271127- NETLBL_NLTYPE_CIPSOV4_NAME, "cipso" },11281128- { NETLBL_NLTYPE_CIPSOV6,11291129- NETLBL_NLTYPE_CIPSOV6_NAME, "cipsov6" },11301130- { NETLBL_NLTYPE_UNLABELED,11311131- NETLBL_NLTYPE_UNLABELED_NAME, "unlabeled" },11321132-};11331133-11341134-/**11351135- * smk_read_nltype - read() for /smack/nltype11361136- * @filp: file pointer, not actually used11371137- * @buf: where to put the result11381138- * @count: maximum to send along11391139- * @ppos: where to start11401140- *11411141- * Returns number of bytes read or error code, as appropriate11421142- */11431143-static ssize_t smk_read_nltype(struct file *filp, char __user *buf,11441144- size_t count, loff_t *ppos)11451145-{11461146- char bound[40];11471147- ssize_t rc;11481148- int i;11491149-11501150- if (count < SMK_LABELLEN)11511151- return -EINVAL;11521152-11531153- if (*ppos != 0)11541154- return 0;11551155-11561156- sprintf(bound, "unknown");11571157-11581158- for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++)11591159- if (smack_net_nltype == netlbl_choices[i].o_number) {11601160- sprintf(bound, "%s", netlbl_choices[i].o_name);11611161- break;11621162- }11631163-11641164- rc = simple_read_from_buffer(buf, count, ppos, bound, strlen(bound));11651165-11661166- return rc;11671167-}11681168-11691169-/**11701170- * smk_write_nltype - write() for /smack/nltype11711171- * @filp: file pointer, not actually used11721172- * @buf: where to get the data from11731173- * @count: bytes sent11741174- * @ppos: where to start11751175- *11761176- * Returns number of bytes written or error code, as appropriate11771177- */11781178-static ssize_t smk_write_nltype(struct file *file, const char __user *buf,11791179- size_t count, loff_t *ppos)11801180-{11811181- char bound[40];11821182- char *cp;11831183- int i;11841184-11851185- if (!capable(CAP_MAC_ADMIN))11861186- return -EPERM;11871187-11881188- if (count >= 40)11891189- return -EINVAL;11901190-11911191- if (copy_from_user(bound, buf, count) != 0)11921192- return -EFAULT;11931193-11941194- bound[count] = '\0';11951195- cp = strchr(bound, ' ');11961196- if (cp != NULL)11971197- *cp = '\0';11981198- cp = strchr(bound, '\n');11991199- if (cp != NULL)12001200- *cp = '\0';12011201-12021202- for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++)12031203- if (strcmp(bound, netlbl_choices[i].o_name) == 0 ||12041204- strcmp(bound, netlbl_choices[i].o_alias) == 0) {12051205- smack_net_nltype = netlbl_choices[i].o_number;12061206- return count;12071207- }12081208- /*12091209- * Not a valid choice.12101210- */12111211- return -EINVAL;12121212-}12131213-12141214-static const struct file_operations smk_nltype_ops = {12151215- .read = smk_read_nltype,12161216- .write = smk_write_nltype,12171217-};12181218-1219894/**1220895 * smk_fill_super - fill the /smackfs superblock1221896 * @sb: the empty superblock···11381021 {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR},11391022 [SMK_AMBIENT] =11401023 {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},11411141- [SMK_NLTYPE] =11421142- {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR},10241024+ [SMK_NETLBLADDR] =10251025+ {"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},11431026 [SMK_ONLYCAP] =11441027 {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},11451028 /* last one */ {""}