summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/security/smack
diff options
context:
space:
mode:
Diffstat (limited to 'ANDROID_3.4.5/security/smack')
-rw-r--r--ANDROID_3.4.5/security/smack/Kconfig10
-rw-r--r--ANDROID_3.4.5/security/smack/Makefile7
-rw-r--r--ANDROID_3.4.5/security/smack/smack.h394
-rw-r--r--ANDROID_3.4.5/security/smack/smack_access.c557
-rw-r--r--ANDROID_3.4.5/security/smack/smack_lsm.c3725
-rw-r--r--ANDROID_3.4.5/security/smack/smackfs.c1620
6 files changed, 0 insertions, 6313 deletions
diff --git a/ANDROID_3.4.5/security/smack/Kconfig b/ANDROID_3.4.5/security/smack/Kconfig
deleted file mode 100644
index 603b0878..00000000
--- a/ANDROID_3.4.5/security/smack/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config SECURITY_SMACK
- bool "Simplified Mandatory Access Control Kernel Support"
- depends on NETLABEL && SECURITY_NETWORK
- default n
- help
- This selects the Simplified Mandatory Access Control Kernel.
- Smack is useful for sensitivity, integrity, and a variety
- of other mandatory security schemes.
- If you are unsure how to answer this question, answer N.
-
diff --git a/ANDROID_3.4.5/security/smack/Makefile b/ANDROID_3.4.5/security/smack/Makefile
deleted file mode 100644
index 67a63aae..00000000
--- a/ANDROID_3.4.5/security/smack/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the SMACK LSM
-#
-
-obj-$(CONFIG_SECURITY_SMACK) := smack.o
-
-smack-y := smack_lsm.o smack_access.o smackfs.o
diff --git a/ANDROID_3.4.5/security/smack/smack.h b/ANDROID_3.4.5/security/smack/smack.h
deleted file mode 100644
index 4ede7199..00000000
--- a/ANDROID_3.4.5/security/smack/smack.h
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
- *
- * Author:
- * Casey Schaufler <casey@schaufler-ca.com>
- *
- */
-
-#ifndef _SECURITY_SMACK_H
-#define _SECURITY_SMACK_H
-
-#include <linux/capability.h>
-#include <linux/spinlock.h>
-#include <linux/security.h>
-#include <linux/in.h>
-#include <net/netlabel.h>
-#include <linux/list.h>
-#include <linux/rculist.h>
-#include <linux/lsm_audit.h>
-
-/*
- * 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)
-
-struct superblock_smack {
- char *smk_root;
- char *smk_floor;
- 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; /* TCP peer label */
-};
-
-/*
- * Inode smack data
- */
-struct inode_smack {
- char *smk_inode; /* label of the fso */
- char *smk_task; /* label of the task */
- char *smk_mmap; /* label of the mmap domain */
- struct mutex smk_lock; /* initialization lock */
- int smk_flags; /* smack inode flags */
-};
-
-struct task_smack {
- char *smk_task; /* label for access control */
- char *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 */
-
-/*
- * A label access rule.
- */
-struct smack_rule {
- struct list_head list;
- char *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 {
- struct list_head list;
- struct sockaddr_in smk_host; /* network address */
- struct in_addr smk_mask; /* network mask */
- char *smk_label; /* label */
-};
-
-/*
- * 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.
- *
- * 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;
- char smk_known[SMK_LABELLEN];
- u32 smk_secid;
- struct smack_cipso *smk_cipso;
- spinlock_t smk_cipsolock; /* for changing cipso map */
- struct list_head smk_rules; /* access rules */
- struct mutex smk_rules_lock; /* lock for the rules */
-};
-
-/*
- * Mount options
- */
-#define SMK_FSDEFAULT "smackfsdef="
-#define SMK_FSFLOOR "smackfsfloor="
-#define SMK_FSHAT "smackfshat="
-#define SMK_FSROOT "smackfsroot="
-
-#define SMACK_CIPSO_OPTION "-CIPSO"
-
-/*
- * How communications on this socket are treated.
- * Usually it's determined by the underlying netlabel code
- * but there are certain cases, including single label hosts
- * and potentially single label interfaces for which the
- * treatment can not be known in advance.
- *
- * The possibility of additional labeling schemes being
- * introduced in the future exists as well.
- */
-#define SMACK_UNLABELED_SOCKET 0
-#define SMACK_CIPSO_SOCKET 1
-
-/*
- * smackfs magic number
- */
-#define SMACK_MAGIC 0x43415d53 /* "SMAC" */
-
-/*
- * 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_MAXCATVAL 63 /* Bigger gets harder */
-#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */
-#define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */
-
-/*
- * Flag for transmute access
- */
-#define MAY_TRANSMUTE 64
-/*
- * Just to make the common cases easier to deal with
- */
-#define MAY_ANYREAD (MAY_READ | MAY_EXEC)
-#define MAY_READWRITE (MAY_READ | MAY_WRITE)
-#define MAY_NOT 0
-
-/*
- * Number of access types used by Smack (rwxat)
- */
-#define SMK_NUM_ACCESS_TYPE 5
-
-/* 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
- * to save some stack
- */
-struct smk_audit_info {
-#ifdef CONFIG_AUDIT
- struct common_audit_data a;
- struct smack_audit_data sad;
-#endif
-};
-/*
- * These functions are in smack_lsm.c
- */
-struct inode_smack *new_inode_smack(char *);
-
-/*
- * These functions are in smack_access.c
- */
-int smk_access_entry(char *, char *, struct list_head *);
-int smk_access(char *, char *, int, struct smk_audit_info *);
-int smk_curacc(char *, u32, struct smk_audit_info *);
-int smack_to_cipso(const char *, struct smack_cipso *);
-char *smack_from_cipso(u32, char *);
-char *smack_from_secid(const u32);
-void smk_parse_smack(const char *string, int len, char *smack);
-char *smk_import(const char *, int);
-struct smack_known *smk_import_entry(const char *, int);
-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 const char *smack_cipso_option;
-
-extern struct smack_known smack_known_floor;
-extern struct smack_known smack_known_hat;
-extern struct smack_known smack_known_huh;
-extern struct smack_known smack_known_invalid;
-extern struct smack_known smack_known_star;
-extern struct smack_known smack_known_web;
-
-extern struct list_head smack_known_list;
-extern struct list_head smk_netlbladdr_list;
-
-extern struct security_operations smack_ops;
-
-/*
- * Stricly for CIPSO level manipulation.
- * Set the category bit number in a smack label sized buffer.
- */
-static inline void smack_catset_bit(int cat, char *catsetp)
-{
- if (cat > SMK_LABELLEN * 8)
- return;
-
- catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
-}
-
-/*
- * Is the directory transmuting?
- */
-static inline int smk_inode_transmutable(const struct inode *isp)
-{
- struct inode_smack *sip = isp->i_security;
- return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0;
-}
-
-/*
- * Present a pointer to the smack label in an inode blob.
- */
-static inline char *smk_of_inode(const struct inode *isp)
-{
- struct inode_smack *sip = isp->i_security;
- return sip->smk_inode;
-}
-
-/*
- * Present a pointer to the smack label in an task blob.
- */
-static inline char *smk_of_task(const struct task_smack *tsp)
-{
- return tsp->smk_task;
-}
-
-/*
- * Present a pointer to the forked smack label in an task blob.
- */
-static inline char *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 char *smk_of_current(void)
-{
- return smk_of_task(current_security());
-}
-
-/*
- * logging functions
- */
-#define SMACK_AUDIT_DENIED 0x1
-#define SMACK_AUDIT_ACCEPT 0x2
-extern int log_policy;
-
-void smack_log(char *subject_label, char *object_label,
- int request,
- int result, struct smk_audit_info *auditdata);
-
-#ifdef CONFIG_AUDIT
-
-/*
- * some inline functions to set up audit data
- * they do nothing if CONFIG_AUDIT is not set
- *
- */
-static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
- char type)
-{
- memset(a, 0, sizeof(*a));
- a->a.type = type;
- 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,
- struct task_struct *t)
-{
- a->a.u.tsk = t;
-}
-static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a,
- struct dentry *d)
-{
- 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.inode = i;
-}
-static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a,
- struct 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;
-}
-
-#else /* no AUDIT */
-
-static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
- char type)
-{
-}
-static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
- struct task_struct *t)
-{
-}
-static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a,
- struct dentry *d)
-{
-}
-static inline void smk_ad_setfield_u_fs_path_mnt(struct smk_audit_info *a,
- struct vfsmount *m)
-{
-}
-static inline void smk_ad_setfield_u_fs_inode(struct smk_audit_info *a,
- struct inode *i)
-{
-}
-static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a,
- struct path p)
-{
-}
-static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
- struct sock *sk)
-{
-}
-#endif
-
-#endif /* _SECURITY_SMACK_H */
diff --git a/ANDROID_3.4.5/security/smack/smack_access.c b/ANDROID_3.4.5/security/smack/smack_access.c
deleted file mode 100644
index c8115f73..00000000
--- a/ANDROID_3.4.5/security/smack/smack_access.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
- *
- * Author:
- * Casey Schaufler <casey@schaufler-ca.com>
- *
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include "smack.h"
-
-struct smack_known smack_known_huh = {
- .smk_known = "?",
- .smk_secid = 2,
- .smk_cipso = NULL,
-};
-
-struct smack_known smack_known_hat = {
- .smk_known = "^",
- .smk_secid = 3,
- .smk_cipso = NULL,
-};
-
-struct smack_known smack_known_star = {
- .smk_known = "*",
- .smk_secid = 4,
- .smk_cipso = NULL,
-};
-
-struct smack_known smack_known_floor = {
- .smk_known = "_",
- .smk_secid = 5,
- .smk_cipso = NULL,
-};
-
-struct smack_known smack_known_invalid = {
- .smk_known = "",
- .smk_secid = 6,
- .smk_cipso = NULL,
-};
-
-struct smack_known smack_known_web = {
- .smk_known = "@",
- .smk_secid = 7,
- .smk_cipso = NULL,
-};
-
-LIST_HEAD(smack_known_list);
-
-/*
- * The initial value needs to be bigger than any of the
- * known values above.
- */
-static u32 smack_next_secid = 10;
-
-/*
- * what events do we log
- * can be overwritten at run-time by /smack/logging
- */
-int log_policy = SMACK_AUDIT_DENIED;
-
-/**
- * smk_access_entry - look up matching access rule
- * @subject_label: a pointer to the subject's Smack label
- * @object_label: a pointer to the object's Smack label
- * @rule_list: the list of rules to search
- *
- * This function looks up the subject/object pair in the
- * access rule list and returns the access mode. If no
- * entry is found returns -ENOENT.
- *
- * NOTE:
- *
- * Earlier versions of this function allowed for labels that
- * were not on the label list. This was done to allow for
- * labels to come over the network that had never been seen
- * before on this host. Unless the receiving socket has the
- * star label this will always result in a failure check. The
- * star labeled socket case is now handled in the networking
- * hooks so there is no case where the label is not on the
- * label list. Checking to see if the address of two labels
- * is the same is now a reliable test.
- *
- * Do the object check first because that is more
- * likely to differ.
- */
-int smk_access_entry(char *subject_label, char *object_label,
- struct list_head *rule_list)
-{
- int may = -ENOENT;
- struct smack_rule *srp;
-
- list_for_each_entry_rcu(srp, rule_list, list) {
- if (srp->smk_object == object_label &&
- srp->smk_subject == subject_label) {
- may = srp->smk_access;
- break;
- }
- }
-
- return may;
-}
-
-/**
- * smk_access - determine if a subject has a specific access to an object
- * @subject_label: a pointer to the subject's Smack label
- * @object_label: a pointer to the object's Smack label
- * @request: the access requested, in "MAY" format
- * @a : a pointer to the audit data
- *
- * This function looks up the subject/object pair in the
- * access rule list and returns 0 if the access is permitted,
- * non zero otherwise.
- *
- * Smack labels are shared on smack_list
- */
-int smk_access(char *subject_label, char *object_label, int request,
- struct smk_audit_info *a)
-{
- struct smack_known *skp;
- int may = MAY_NOT;
- int rc = 0;
-
- /*
- * Hardcoded comparisons.
- *
- * A star subject can't access any object.
- */
- if (subject_label == smack_known_star.smk_known) {
- rc = -EACCES;
- goto out_audit;
- }
- /*
- * 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_web.smk_known ||
- subject_label == smack_known_web.smk_known)
- goto out_audit;
- /*
- * A star object can be accessed by any subject.
- */
- if (object_label == smack_known_star.smk_known)
- goto out_audit;
- /*
- * An object can be accessed in any way by a subject
- * with the same label.
- */
- if (subject_label == object_label)
- goto out_audit;
- /*
- * A hat subject can read any object.
- * A floor object can be read by any subject.
- */
- if ((request & MAY_ANYREAD) == request) {
- if (object_label == smack_known_floor.smk_known)
- goto out_audit;
- if (subject_label == smack_known_hat.smk_known)
- goto out_audit;
- }
- /*
- * Beyond here an explicit relationship is required.
- * If the requested access is contained in the available
- * access (e.g. read is included in readwrite) it's
- * good. A negative response from smk_access_entry()
- * indicates there is no entry for this pair.
- */
- skp = smk_find_entry(subject_label);
- rcu_read_lock();
- may = smk_access_entry(subject_label, object_label, &skp->smk_rules);
- rcu_read_unlock();
-
- if (may > 0 && (request & may) == request)
- goto out_audit;
-
- rc = -EACCES;
-out_audit:
-#ifdef CONFIG_AUDIT
- if (a)
- smack_log(subject_label, object_label, request, rc, a);
-#endif
- return rc;
-}
-
-/**
- * smk_curacc - determine if current has a specific access to an object
- * @obj_label: a pointer to the object's Smack label
- * @mode: the access requested, in "MAY" format
- * @a : common audit data
- *
- * This function checks the current subject label/object label pair
- * in the access rule list and returns 0 if the access is permitted,
- * non zero otherwise. It allows that current may have the capability
- * to override the rules.
- */
-int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
-{
- struct task_smack *tsp = current_security();
- char *sp = smk_of_task(tsp);
- int may;
- int rc;
-
- /*
- * Check the global rule list
- */
- rc = smk_access(sp, obj_label, mode, NULL);
- if (rc == 0) {
- /*
- * If there is an entry in the task's rule list
- * it can further restrict access.
- */
- may = smk_access_entry(sp, obj_label, &tsp->smk_rules);
- if (may < 0)
- goto out_audit;
- if ((mode & may) == mode)
- goto out_audit;
- rc = -EACCES;
- }
-
- /*
- * Return if a specific label has been designated as the
- * only one that gets privilege and current does not
- * have that label.
- */
- if (smack_onlycap != NULL && smack_onlycap != sp)
- goto out_audit;
-
- if (capable(CAP_MAC_OVERRIDE))
- rc = 0;
-
-out_audit:
-#ifdef CONFIG_AUDIT
- if (a)
- smack_log(sp, obj_label, mode, rc, a);
-#endif
- return rc;
-}
-
-#ifdef CONFIG_AUDIT
-/**
- * smack_str_from_perm : helper to transalate an int to a
- * readable string
- * @string : the string to fill
- * @access : the int
- *
- */
-static inline void smack_str_from_perm(char *string, int access)
-{
- int i = 0;
- if (access & MAY_READ)
- string[i++] = 'r';
- if (access & MAY_WRITE)
- string[i++] = 'w';
- if (access & MAY_EXEC)
- string[i++] = 'x';
- if (access & MAY_APPEND)
- string[i++] = 'a';
- string[i] = '\0';
-}
-/**
- * smack_log_callback - SMACK specific information
- * will be called by generic audit code
- * @ab : the audit_buffer
- * @a : audit_data
- *
- */
-static void smack_log_callback(struct audit_buffer *ab, void *a)
-{
- struct common_audit_data *ad = a;
- struct smack_audit_data *sad = ad->smack_audit_data;
- audit_log_format(ab, "lsm=SMACK fn=%s action=%s",
- ad->smack_audit_data->function,
- sad->result ? "denied" : "granted");
- audit_log_format(ab, " subject=");
- audit_log_untrustedstring(ab, sad->subject);
- audit_log_format(ab, " object=");
- audit_log_untrustedstring(ab, sad->object);
- audit_log_format(ab, " requested=%s", sad->request);
-}
-
-/**
- * smack_log - Audit the granting or denial of permissions.
- * @subject_label : smack label of the requester
- * @object_label : smack label of the object being accessed
- * @request: requested permissions
- * @result: result from smk_access
- * @a: auxiliary audit data
- *
- * Audit the granting or denial of permissions in accordance
- * with the policy.
- */
-void smack_log(char *subject_label, char *object_label, int request,
- int result, struct smk_audit_info *ad)
-{
- char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
- struct smack_audit_data *sad;
- struct common_audit_data *a = &ad->a;
-
- /* check if we have to log the current event */
- if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
- return;
- if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
- return;
-
- sad = a->smack_audit_data;
-
- if (sad->function == NULL)
- sad->function = "unknown";
-
- /* end preparing the audit data */
- smack_str_from_perm(request_buffer, request);
- sad->subject = subject_label;
- sad->object = object_label;
- sad->request = request_buffer;
- sad->result = result;
-
- common_lsm_audit(a, smack_log_callback, NULL);
-}
-#else /* #ifdef CONFIG_AUDIT */
-void smack_log(char *subject_label, char *object_label, int request,
- int result, struct smk_audit_info *ad)
-{
-}
-#endif
-
-static DEFINE_MUTEX(smack_known_lock);
-
-/**
- * smk_find_entry - find a label on the list, return the list entry
- * @string: a text string that might be a Smack label
- *
- * Returns a pointer to the entry in the label list that
- * matches the passed string.
- */
-struct smack_known *smk_find_entry(const char *string)
-{
- struct smack_known *skp;
-
- list_for_each_entry_rcu(skp, &smack_known_list, list) {
- if (strncmp(skp->smk_known, string, SMK_MAXLEN) == 0)
- return skp;
- }
-
- return NULL;
-}
-
-/**
- * smk_parse_smack - parse smack label from a text string
- * @string: a text string that might contain a Smack label
- * @len: the maximum size, or zero if it is NULL terminated.
- * @smack: parsed smack label, or NULL if parse error
- */
-void smk_parse_smack(const char *string, int len, char *smack)
-{
- int found;
- int i;
-
- if (len <= 0 || len > SMK_MAXLEN)
- len = SMK_MAXLEN;
-
- for (i = 0, found = 0; i < SMK_LABELLEN; i++) {
- if (found)
- smack[i] = '\0';
- else if (i >= len || string[i] > '~' || string[i] <= ' ' ||
- string[i] == '/' || string[i] == '"' ||
- string[i] == '\\' || string[i] == '\'') {
- smack[i] = '\0';
- found = 1;
- } else
- smack[i] = string[i];
- }
-}
-
-/**
- * smk_import_entry - import a label, return the list entry
- * @string: a text string that might be a Smack label
- * @len: the maximum size, or zero if it is NULL terminated.
- *
- * Returns a pointer to the entry in the label list that
- * matches the passed string, adding it if necessary.
- */
-struct smack_known *smk_import_entry(const char *string, int len)
-{
- struct smack_known *skp;
- char smack[SMK_LABELLEN];
-
- smk_parse_smack(string, len, smack);
- if (smack[0] == '\0')
- return NULL;
-
- mutex_lock(&smack_known_lock);
-
- skp = smk_find_entry(smack);
-
- if (skp == NULL) {
- skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
- if (skp != NULL) {
- strncpy(skp->smk_known, smack, SMK_MAXLEN);
- skp->smk_secid = smack_next_secid++;
- skp->smk_cipso = NULL;
- INIT_LIST_HEAD(&skp->smk_rules);
- spin_lock_init(&skp->smk_cipsolock);
- mutex_init(&skp->smk_rules_lock);
- /*
- * Make sure that the entry is actually
- * filled before putting it on the list.
- */
- list_add_rcu(&skp->list, &smack_known_list);
- }
- }
-
- mutex_unlock(&smack_known_lock);
-
- return skp;
-}
-
-/**
- * smk_import - import a smack label
- * @string: a text string that might be a Smack label
- * @len: the maximum size, or zero if it is NULL terminated.
- *
- * Returns a pointer to the label in the label list that
- * matches the passed string, adding it if necessary.
- */
-char *smk_import(const char *string, int len)
-{
- struct smack_known *skp;
-
- /* labels cannot begin with a '-' */
- if (string[0] == '-')
- return NULL;
- skp = smk_import_entry(string, len);
- if (skp == NULL)
- return NULL;
- return skp->smk_known;
-}
-
-/**
- * smack_from_secid - find the Smack label associated with a secid
- * @secid: an integer that might be associated with a Smack label
- *
- * Returns a pointer to the appropriate Smack label if there is one,
- * otherwise a pointer to the invalid Smack label.
- */
-char *smack_from_secid(const u32 secid)
-{
- struct smack_known *skp;
-
- rcu_read_lock();
- list_for_each_entry_rcu(skp, &smack_known_list, list) {
- if (skp->smk_secid == secid) {
- rcu_read_unlock();
- return skp->smk_known;
- }
- }
-
- /*
- * If we got this far someone asked for the translation
- * of a secid that is not on the list.
- */
- rcu_read_unlock();
- return smack_known_invalid.smk_known;
-}
-
-/**
- * smack_to_secid - find the secid associated with a Smack label
- * @smack: the Smack label
- *
- * Returns the appropriate secid if there is one,
- * otherwise 0
- */
-u32 smack_to_secid(const char *smack)
-{
- struct smack_known *skp;
-
- rcu_read_lock();
- list_for_each_entry_rcu(skp, &smack_known_list, list) {
- if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
- rcu_read_unlock();
- return skp->smk_secid;
- }
- }
- rcu_read_unlock();
- return 0;
-}
-
-/**
- * smack_from_cipso - find the Smack label associated with a CIPSO option
- * @level: Bell & LaPadula level from the network
- * @cp: Bell & LaPadula categories from the network
- *
- * This is a simple lookup in the label table.
- *
- * Return the matching label from the label list or NULL.
- */
-char *smack_from_cipso(u32 level, char *cp)
-{
- struct smack_known *kp;
- char *final = NULL;
-
- rcu_read_lock();
- list_for_each_entry(kp, &smack_known_list, list) {
- if (kp->smk_cipso == NULL)
- continue;
-
- spin_lock_bh(&kp->smk_cipsolock);
-
- if (kp->smk_cipso->smk_level == level &&
- memcmp(kp->smk_cipso->smk_catset, cp, SMK_LABELLEN) == 0)
- final = kp->smk_known;
-
- spin_unlock_bh(&kp->smk_cipsolock);
-
- if (final != NULL)
- break;
- }
- rcu_read_unlock();
-
- return final;
-}
-
-/**
- * smack_to_cipso - find the CIPSO option to go with a Smack label
- * @smack: a pointer to the smack label in question
- * @cp: where to put the result
- *
- * Returns zero if a value is available, non-zero otherwise.
- */
-int smack_to_cipso(const char *smack, struct smack_cipso *cp)
-{
- struct smack_known *kp;
- int found = 0;
-
- rcu_read_lock();
- list_for_each_entry_rcu(kp, &smack_known_list, list) {
- if (kp->smk_known == smack ||
- strcmp(kp->smk_known, smack) == 0) {
- found = 1;
- break;
- }
- }
- rcu_read_unlock();
-
- if (found == 0 || kp->smk_cipso == NULL)
- return -ENOENT;
-
- memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));
- return 0;
-}
diff --git a/ANDROID_3.4.5/security/smack/smack_lsm.c b/ANDROID_3.4.5/security/smack/smack_lsm.c
deleted file mode 100644
index 45c32f07..00000000
--- a/ANDROID_3.4.5/security/smack/smack_lsm.c
+++ /dev/null
@@ -1,3725 +0,0 @@
-/*
- * Simplified MAC Kernel (smack) security module
- *
- * This file contains the smack hook function implementations.
- *
- * Authors:
- * Casey Schaufler <casey@schaufler-ca.com>
- * Jarkko Sakkinen <jarkko.sakkinen@intel.com>
- *
- * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
- * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
- * Paul Moore <paul@paul-moore.com>
- * Copyright (C) 2010 Nokia Corporation
- * Copyright (C) 2011 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- */
-
-#include <linux/xattr.h>
-#include <linux/pagemap.h>
-#include <linux/mount.h>
-#include <linux/stat.h>
-#include <linux/kd.h>
-#include <asm/ioctls.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/pipe_fs_i.h>
-#include <net/netlabel.h>
-#include <net/cipso_ipv4.h>
-#include <linux/audit.h>
-#include <linux/magic.h>
-#include <linux/dcache.h>
-#include <linux/personality.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/binfmts.h>
-#include "smack.h"
-
-#define task_security(task) (task_cred_xxx((task), security))
-
-#define TRANS_TRUE "TRUE"
-#define TRANS_TRUE_SIZE 4
-
-/**
- * smk_fetch - Fetch the smack label from a file.
- * @ip: a pointer to the inode
- * @dp: a pointer to the dentry
- *
- * Returns a pointer to the master list entry for the Smack label
- * or NULL if there was no label to fetch.
- */
-static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp)
-{
- int rc;
- char in[SMK_LABELLEN];
-
- if (ip->i_op->getxattr == NULL)
- return NULL;
-
- rc = ip->i_op->getxattr(dp, name, in, SMK_LABELLEN);
- if (rc < 0)
- return NULL;
-
- return smk_import(in, rc);
-}
-
-/**
- * new_inode_smack - allocate an inode security blob
- * @smack: a pointer to the Smack label to use in the blob
- *
- * Returns the new blob or NULL if there's no memory available
- */
-struct inode_smack *new_inode_smack(char *smack)
-{
- struct inode_smack *isp;
-
- isp = kzalloc(sizeof(struct inode_smack), GFP_KERNEL);
- if (isp == NULL)
- return NULL;
-
- isp->smk_inode = smack;
- isp->smk_flags = 0;
- mutex_init(&isp->smk_lock);
-
- return isp;
-}
-
-/**
- * new_task_smack - allocate a task security blob
- * @smack: a pointer to the Smack label to use in the blob
- *
- * Returns the new blob or NULL if there's no memory available
- */
-static struct task_smack *new_task_smack(char *task, char *forked, gfp_t gfp)
-{
- struct task_smack *tsp;
-
- tsp = kzalloc(sizeof(struct task_smack), gfp);
- if (tsp == NULL)
- return NULL;
-
- tsp->smk_task = task;
- tsp->smk_forked = forked;
- INIT_LIST_HEAD(&tsp->smk_rules);
- mutex_init(&tsp->smk_rules_lock);
-
- return tsp;
-}
-
-/**
- * smk_copy_rules - copy a rule set
- * @nhead - new rules header pointer
- * @ohead - old rules header pointer
- *
- * Returns 0 on success, -ENOMEM on error
- */
-static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
- gfp_t gfp)
-{
- struct smack_rule *nrp;
- struct smack_rule *orp;
- int rc = 0;
-
- INIT_LIST_HEAD(nhead);
-
- list_for_each_entry_rcu(orp, ohead, list) {
- nrp = kzalloc(sizeof(struct smack_rule), gfp);
- if (nrp == NULL) {
- rc = -ENOMEM;
- break;
- }
- *nrp = *orp;
- list_add_rcu(&nrp->list, nhead);
- }
- return rc;
-}
-
-/*
- * LSM hooks.
- * We he, that is fun!
- */
-
-/**
- * smack_ptrace_access_check - Smack approval on PTRACE_ATTACH
- * @ctp: child task pointer
- * @mode: ptrace attachment mode
- *
- * Returns 0 if access is OK, an error code otherwise
- *
- * Do the capability checks, and require read and write.
- */
-static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
-{
- int rc;
- struct smk_audit_info ad;
- char *tsp;
-
- rc = cap_ptrace_access_check(ctp, mode);
- if (rc != 0)
- return rc;
-
- tsp = smk_of_task(task_security(ctp));
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
- smk_ad_setfield_u_tsk(&ad, ctp);
-
- rc = smk_curacc(tsp, MAY_READWRITE, &ad);
- return rc;
-}
-
-/**
- * smack_ptrace_traceme - Smack approval on PTRACE_TRACEME
- * @ptp: parent task pointer
- *
- * Returns 0 if access is OK, an error code otherwise
- *
- * Do the capability checks, and require read and write.
- */
-static int smack_ptrace_traceme(struct task_struct *ptp)
-{
- int rc;
- struct smk_audit_info ad;
- char *tsp;
-
- rc = cap_ptrace_traceme(ptp);
- if (rc != 0)
- return rc;
-
- tsp = smk_of_task(task_security(ptp));
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
- smk_ad_setfield_u_tsk(&ad, ptp);
-
- rc = smk_curacc(tsp, MAY_READWRITE, &ad);
- return rc;
-}
-
-/**
- * smack_syslog - Smack approval on syslog
- * @type: message type
- *
- * Require that the task has the floor label
- *
- * Returns 0 on success, error code otherwise.
- */
-static int smack_syslog(int typefrom_file)
-{
- int rc = 0;
- char *sp = smk_of_current();
-
- if (capable(CAP_MAC_OVERRIDE))
- return 0;
-
- if (sp != smack_known_floor.smk_known)
- rc = -EACCES;
-
- return rc;
-}
-
-
-/*
- * Superblock Hooks.
- */
-
-/**
- * smack_sb_alloc_security - allocate a superblock blob
- * @sb: the superblock getting the blob
- *
- * Returns 0 on success or -ENOMEM on error.
- */
-static int smack_sb_alloc_security(struct super_block *sb)
-{
- struct superblock_smack *sbsp;
-
- sbsp = kzalloc(sizeof(struct superblock_smack), GFP_KERNEL);
-
- if (sbsp == NULL)
- return -ENOMEM;
-
- sbsp->smk_root = smack_known_floor.smk_known;
- sbsp->smk_default = smack_known_floor.smk_known;
- sbsp->smk_floor = smack_known_floor.smk_known;
- sbsp->smk_hat = smack_known_hat.smk_known;
- sbsp->smk_initialized = 0;
- spin_lock_init(&sbsp->smk_sblock);
-
- sb->s_security = sbsp;
-
- return 0;
-}
-
-/**
- * smack_sb_free_security - free a superblock blob
- * @sb: the superblock getting the blob
- *
- */
-static void smack_sb_free_security(struct super_block *sb)
-{
- kfree(sb->s_security);
- sb->s_security = NULL;
-}
-
-/**
- * smack_sb_copy_data - copy mount options data for processing
- * @orig: where to start
- * @smackopts: mount options string
- *
- * Returns 0 on success or -ENOMEM on error.
- *
- * Copy the Smack specific mount options out of the mount
- * options list.
- */
-static int smack_sb_copy_data(char *orig, char *smackopts)
-{
- char *cp, *commap, *otheropts, *dp;
-
- otheropts = (char *)get_zeroed_page(GFP_KERNEL);
- if (otheropts == NULL)
- return -ENOMEM;
-
- for (cp = orig, commap = orig; commap != NULL; cp = commap + 1) {
- if (strstr(cp, SMK_FSDEFAULT) == cp)
- dp = smackopts;
- else if (strstr(cp, SMK_FSFLOOR) == cp)
- dp = smackopts;
- else if (strstr(cp, SMK_FSHAT) == cp)
- dp = smackopts;
- else if (strstr(cp, SMK_FSROOT) == cp)
- dp = smackopts;
- else
- dp = otheropts;
-
- commap = strchr(cp, ',');
- if (commap != NULL)
- *commap = '\0';
-
- if (*dp != '\0')
- strcat(dp, ",");
- strcat(dp, cp);
- }
-
- strcpy(orig, otheropts);
- free_page((unsigned long)otheropts);
-
- return 0;
-}
-
-/**
- * smack_sb_kern_mount - Smack specific mount processing
- * @sb: the file system superblock
- * @flags: the mount flags
- * @data: the smack mount options
- *
- * Returns 0 on success, an error code on failure
- */
-static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
-{
- struct dentry *root = sb->s_root;
- struct inode *inode = root->d_inode;
- struct superblock_smack *sp = sb->s_security;
- struct inode_smack *isp;
- char *op;
- char *commap;
- char *nsp;
-
- spin_lock(&sp->smk_sblock);
- if (sp->smk_initialized != 0) {
- spin_unlock(&sp->smk_sblock);
- return 0;
- }
- sp->smk_initialized = 1;
- spin_unlock(&sp->smk_sblock);
-
- for (op = data; op != NULL; op = commap) {
- commap = strchr(op, ',');
- if (commap != NULL)
- *commap++ = '\0';
-
- if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) {
- op += strlen(SMK_FSHAT);
- nsp = smk_import(op, 0);
- if (nsp != NULL)
- sp->smk_hat = nsp;
- } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) {
- op += strlen(SMK_FSFLOOR);
- nsp = smk_import(op, 0);
- if (nsp != NULL)
- sp->smk_floor = nsp;
- } else if (strncmp(op, SMK_FSDEFAULT,
- strlen(SMK_FSDEFAULT)) == 0) {
- op += strlen(SMK_FSDEFAULT);
- nsp = smk_import(op, 0);
- if (nsp != NULL)
- sp->smk_default = nsp;
- } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) {
- op += strlen(SMK_FSROOT);
- nsp = smk_import(op, 0);
- if (nsp != NULL)
- sp->smk_root = nsp;
- }
- }
-
- /*
- * Initialize the root inode.
- */
- isp = inode->i_security;
- if (isp == NULL)
- inode->i_security = new_inode_smack(sp->smk_root);
- else
- isp->smk_inode = sp->smk_root;
-
- return 0;
-}
-
-/**
- * smack_sb_statfs - Smack check on statfs
- * @dentry: identifies the file system in question
- *
- * Returns 0 if current can read the floor of the filesystem,
- * and error code otherwise
- */
-static int smack_sb_statfs(struct dentry *dentry)
-{
- struct superblock_smack *sbp = dentry->d_sb->s_security;
- int rc;
- struct smk_audit_info ad;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
- smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
-
- rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad);
- return rc;
-}
-
-/**
- * smack_sb_mount - Smack check for mounting
- * @dev_name: unused
- * @path: mount point
- * @type: unused
- * @flags: unused
- * @data: unused
- *
- * Returns 0 if current can write the floor of the filesystem
- * being mounted on, an error code otherwise.
- */
-static int smack_sb_mount(char *dev_name, struct path *path,
- char *type, unsigned long flags, void *data)
-{
- struct superblock_smack *sbp = path->dentry->d_sb->s_security;
- struct smk_audit_info ad;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
- smk_ad_setfield_u_fs_path(&ad, *path);
-
- return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad);
-}
-
-/**
- * smack_sb_umount - Smack check for unmounting
- * @mnt: file system to unmount
- * @flags: unused
- *
- * Returns 0 if current can write the floor of the filesystem
- * being unmounted, an error code otherwise.
- */
-static int smack_sb_umount(struct vfsmount *mnt, int flags)
-{
- struct superblock_smack *sbp;
- struct smk_audit_info ad;
- struct path path;
-
- path.dentry = mnt->mnt_root;
- path.mnt = mnt;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
- smk_ad_setfield_u_fs_path(&ad, path);
-
- sbp = path.dentry->d_sb->s_security;
- return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad);
-}
-
-/*
- * BPRM hooks
- */
-
-/**
- * smack_bprm_set_creds - set creds for exec
- * @bprm: the exec information
- *
- * Returns 0 if it gets a blob, -ENOMEM otherwise
- */
-static int smack_bprm_set_creds(struct linux_binprm *bprm)
-{
- struct inode *inode = bprm->file->f_path.dentry->d_inode;
- struct task_smack *bsp = bprm->cred->security;
- struct inode_smack *isp;
- int rc;
-
- rc = cap_bprm_set_creds(bprm);
- if (rc != 0)
- return rc;
-
- if (bprm->cred_prepared)
- return 0;
-
- isp = inode->i_security;
- if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task)
- return 0;
-
- if (bprm->unsafe)
- return -EPERM;
-
- bsp->smk_task = isp->smk_task;
- bprm->per_clear |= PER_CLEAR_ON_SETID;
-
- return 0;
-}
-
-/**
- * smack_bprm_committing_creds - Prepare to install the new credentials
- * from bprm.
- *
- * @bprm: binprm for exec
- */
-static void smack_bprm_committing_creds(struct linux_binprm *bprm)
-{
- struct task_smack *bsp = bprm->cred->security;
-
- if (bsp->smk_task != bsp->smk_forked)
- current->pdeath_signal = 0;
-}
-
-/**
- * smack_bprm_secureexec - Return the decision to use secureexec.
- * @bprm: binprm for exec
- *
- * Returns 0 on success.
- */
-static int smack_bprm_secureexec(struct linux_binprm *bprm)
-{
- struct task_smack *tsp = current_security();
- int ret = cap_bprm_secureexec(bprm);
-
- if (!ret && (tsp->smk_task != tsp->smk_forked))
- ret = 1;
-
- return ret;
-}
-
-/*
- * Inode hooks
- */
-
-/**
- * smack_inode_alloc_security - allocate an inode blob
- * @inode: the inode in need of a blob
- *
- * Returns 0 if it gets a blob, -ENOMEM otherwise
- */
-static int smack_inode_alloc_security(struct inode *inode)
-{
- inode->i_security = new_inode_smack(smk_of_current());
- if (inode->i_security == NULL)
- return -ENOMEM;
- return 0;
-}
-
-/**
- * smack_inode_free_security - free an inode blob
- * @inode: the inode with a blob
- *
- * Clears the blob pointer in inode
- */
-static void smack_inode_free_security(struct inode *inode)
-{
- kfree(inode->i_security);
- inode->i_security = NULL;
-}
-
-/**
- * smack_inode_init_security - copy out the smack from an inode
- * @inode: the inode
- * @dir: unused
- * @qstr: unused
- * @name: where to put the attribute name
- * @value: where to put the attribute value
- * @len: where to put the length of the attribute
- *
- * Returns 0 if it all works out, -ENOMEM if there's no memory
- */
-static int smack_inode_init_security(struct inode *inode, struct inode *dir,
- const struct qstr *qstr, char **name,
- void **value, size_t *len)
-{
- struct smack_known *skp;
- char *csp = smk_of_current();
- char *isp = smk_of_inode(inode);
- char *dsp = smk_of_inode(dir);
- int may;
-
- if (name) {
- *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL);
- if (*name == NULL)
- return -ENOMEM;
- }
-
- if (value) {
- skp = smk_find_entry(csp);
- rcu_read_lock();
- may = smk_access_entry(csp, dsp, &skp->smk_rules);
- rcu_read_unlock();
-
- /*
- * If the access rule allows transmutation and
- * the directory requests transmutation then
- * by all means transmute.
- */
- if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
- smk_inode_transmutable(dir))
- isp = dsp;
-
- *value = kstrdup(isp, GFP_KERNEL);
- if (*value == NULL)
- return -ENOMEM;
- }
-
- if (len)
- *len = strlen(isp) + 1;
-
- return 0;
-}
-
-/**
- * smack_inode_link - Smack check on link
- * @old_dentry: the existing object
- * @dir: unused
- * @new_dentry: the new object
- *
- * Returns 0 if access is permitted, an error code otherwise
- */
-static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *new_dentry)
-{
- char *isp;
- struct smk_audit_info ad;
- int rc;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
- smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
-
- isp = smk_of_inode(old_dentry->d_inode);
- rc = smk_curacc(isp, MAY_WRITE, &ad);
-
- if (rc == 0 && new_dentry->d_inode != NULL) {
- isp = smk_of_inode(new_dentry->d_inode);
- smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
- rc = smk_curacc(isp, MAY_WRITE, &ad);
- }
-
- return rc;
-}
-
-/**
- * smack_inode_unlink - Smack check on inode deletion
- * @dir: containing directory object
- * @dentry: file to unlink
- *
- * Returns 0 if current can write the containing directory
- * and the object, error code otherwise
- */
-static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
-{
- struct inode *ip = dentry->d_inode;
- struct smk_audit_info ad;
- int rc;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
- smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
-
- /*
- * You need write access to the thing you're unlinking
- */
- rc = smk_curacc(smk_of_inode(ip), MAY_WRITE, &ad);
- if (rc == 0) {
- /*
- * You also need write access to the containing directory
- */
- smk_ad_setfield_u_fs_path_dentry(&ad, NULL);
- smk_ad_setfield_u_fs_inode(&ad, dir);
- rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
- }
- return rc;
-}
-
-/**
- * smack_inode_rmdir - Smack check on directory deletion
- * @dir: containing directory object
- * @dentry: directory to unlink
- *
- * Returns 0 if current can write the containing directory
- * and the directory, error code otherwise
- */
-static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
-{
- struct smk_audit_info ad;
- int rc;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
- smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
-
- /*
- * You need write access to the thing you're removing
- */
- rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
- if (rc == 0) {
- /*
- * You also need write access to the containing directory
- */
- smk_ad_setfield_u_fs_path_dentry(&ad, NULL);
- smk_ad_setfield_u_fs_inode(&ad, dir);
- rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
- }
-
- return rc;
-}
-
-/**
- * smack_inode_rename - Smack check on rename
- * @old_inode: the old directory
- * @old_dentry: unused
- * @new_inode: the new directory
- * @new_dentry: unused
- *
- * Read and write access is required on both the old and
- * new directories.
- *
- * Returns 0 if access is permitted, an error code otherwise
- */
-static int smack_inode_rename(struct inode *old_inode,
- struct dentry *old_dentry,
- struct inode *new_inode,
- struct dentry *new_dentry)
-{
- int rc;
- char *isp;
- struct smk_audit_info ad;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
- smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
-
- isp = smk_of_inode(old_dentry->d_inode);
- rc = smk_curacc(isp, MAY_READWRITE, &ad);
-
- if (rc == 0 && new_dentry->d_inode != NULL) {
- isp = smk_of_inode(new_dentry->d_inode);
- smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
- rc = smk_curacc(isp, MAY_READWRITE, &ad);
- }
- return rc;
-}
-
-/**
- * smack_inode_permission - Smack version of permission()
- * @inode: the inode in question
- * @mask: the access requested
- *
- * This is the important Smack hook.
- *
- * Returns 0 if access is permitted, -EACCES otherwise
- */
-static int smack_inode_permission(struct inode *inode, int mask)
-{
- struct smk_audit_info ad;
- int no_block = mask & MAY_NOT_BLOCK;
-
- mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
- /*
- * No permission to check. Existence test. Yup, it's there.
- */
- if (mask == 0)
- return 0;
-
- /* May be droppable after audit */
- if (no_block)
- return -ECHILD;
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE);
- smk_ad_setfield_u_fs_inode(&ad, inode);
- return smk_curacc(smk_of_inode(inode), mask, &ad);
-}
-
-/**
- * smack_inode_setattr - Smack check for setting attributes
- * @dentry: the object
- * @iattr: for the force flag
- *
- * Returns 0 if access is permitted, an error code otherwise
- */
-static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
-{
- struct smk_audit_info ad;
- /*
- * Need to allow for clearing the setuid bit.
- */
- if (iattr->ia_valid & ATTR_FORCE)
- return 0;
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
- smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
-
- return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
-}
-
-/**
- * smack_inode_getattr - Smack check for getting attributes
- * @mnt: unused
- * @dentry: the object
- *
- * Returns 0 if access is permitted, an error code otherwise
- */
-static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
-{
- struct smk_audit_info ad;
- struct path path;
-
- path.dentry = dentry;
- path.mnt = mnt;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
- smk_ad_setfield_u_fs_path(&ad, path);
- return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
-}
-
-/**
- * smack_inode_setxattr - Smack check for setting xattrs
- * @dentry: the object
- * @name: name of the attribute
- * @value: unused
- * @size: unused
- * @flags: unused
- *
- * This protects the Smack attribute explicitly.
- *
- * Returns 0 if access is permitted, an error code otherwise
- */
-static int smack_inode_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
-{
- struct smk_audit_info ad;
- int rc = 0;
-
- if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
- strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
- strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
- strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
- strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
- if (!capable(CAP_MAC_ADMIN))
- rc = -EPERM;
- /*
- * check label validity here so import wont fail on
- * post_setxattr
- */
- if (size == 0 || size >= SMK_LABELLEN ||
- smk_import(value, size) == NULL)
- rc = -EINVAL;
- } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
- if (!capable(CAP_MAC_ADMIN))
- rc = -EPERM;
- if (size != TRANS_TRUE_SIZE ||
- strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
- rc = -EINVAL;
- } else
- rc = cap_inode_setxattr(dentry, name, value, size, flags);
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
- smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
-
- if (rc == 0)
- rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
-
- return rc;
-}
-
-/**
- * smack_inode_post_setxattr - Apply the Smack update approved above
- * @dentry: object
- * @name: attribute name
- * @value: attribute value
- * @size: attribute size
- * @flags: unused
- *
- * Set the pointer in the inode blob to the entry found
- * in the master label list.
- */
-static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
-{
- char *nsp;
- struct inode_smack *isp = dentry->d_inode->i_security;
-
- if (strcmp(name, XATTR_NAME_SMACK) == 0) {
- nsp = smk_import(value, size);
- if (nsp != NULL)
- isp->smk_inode = nsp;
- else
- isp->smk_inode = smack_known_invalid.smk_known;
- } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) {
- nsp = smk_import(value, size);
- if (nsp != NULL)
- isp->smk_task = nsp;
- else
- isp->smk_task = smack_known_invalid.smk_known;
- } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
- nsp = smk_import(value, size);
- if (nsp != NULL)
- isp->smk_mmap = nsp;
- else
- isp->smk_mmap = smack_known_invalid.smk_known;
- } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0)
- isp->smk_flags |= SMK_INODE_TRANSMUTE;
-
- return;
-}
-
-/**
- * smack_inode_getxattr - Smack check on getxattr
- * @dentry: the object
- * @name: unused
- *
- * Returns 0 if access is permitted, an error code otherwise
- */
-static int smack_inode_getxattr(struct dentry *dentry, const char *name)
-{
- struct smk_audit_info ad;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
- smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
-
- return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
-}
-
-/**
- * smack_inode_removexattr - Smack check on removexattr
- * @dentry: the object
- * @name: name of the attribute
- *
- * Removing the Smack attribute requires CAP_MAC_ADMIN
- *
- * Returns 0 if access is permitted, an error code otherwise
- */
-static int smack_inode_removexattr(struct dentry *dentry, const char *name)
-{
- struct inode_smack *isp;
- struct smk_audit_info ad;
- int rc = 0;
-
- if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
- strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
- strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
- strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
- strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 ||
- strcmp(name, XATTR_NAME_SMACKMMAP)) {
- if (!capable(CAP_MAC_ADMIN))
- rc = -EPERM;
- } else
- rc = cap_inode_removexattr(dentry, name);
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
- smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
- if (rc == 0)
- rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
-
- if (rc == 0) {
- isp = dentry->d_inode->i_security;
- isp->smk_task = NULL;
- isp->smk_mmap = NULL;
- }
-
- return rc;
-}
-
-/**
- * smack_inode_getsecurity - get smack xattrs
- * @inode: the object
- * @name: attribute name
- * @buffer: where to put the result
- * @alloc: unused
- *
- * Returns the size of the attribute or an error code
- */
-static int smack_inode_getsecurity(const struct inode *inode,
- const char *name, void **buffer,
- bool alloc)
-{
- struct socket_smack *ssp;
- struct socket *sock;
- struct super_block *sbp;
- struct inode *ip = (struct inode *)inode;
- char *isp;
- int ilen;
- int rc = 0;
-
- if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
- isp = smk_of_inode(inode);
- ilen = strlen(isp) + 1;
- *buffer = isp;
- return ilen;
- }
-
- /*
- * The rest of the Smack xattrs are only on sockets.
- */
- sbp = ip->i_sb;
- if (sbp->s_magic != SOCKFS_MAGIC)
- return -EOPNOTSUPP;
-
- sock = SOCKET_I(ip);
- if (sock == NULL || sock->sk == NULL)
- return -EOPNOTSUPP;
-
- ssp = sock->sk->sk_security;
-
- if (strcmp(name, XATTR_SMACK_IPIN) == 0)
- isp = ssp->smk_in;
- else if (strcmp(name, XATTR_SMACK_IPOUT) == 0)
- isp = ssp->smk_out;
- else
- return -EOPNOTSUPP;
-
- ilen = strlen(isp) + 1;
- if (rc == 0) {
- *buffer = isp;
- rc = ilen;
- }
-
- return rc;
-}
-
-
-/**
- * smack_inode_listsecurity - list the Smack attributes
- * @inode: the object
- * @buffer: where they go
- * @buffer_size: size of buffer
- *
- * Returns 0 on success, -EINVAL otherwise
- */
-static int smack_inode_listsecurity(struct inode *inode, char *buffer,
- size_t buffer_size)
-{
- int len = strlen(XATTR_NAME_SMACK);
-
- if (buffer != NULL && len <= buffer_size) {
- memcpy(buffer, XATTR_NAME_SMACK, len);
- return len;
- }
- return -EINVAL;
-}
-
-/**
- * smack_inode_getsecid - Extract inode's security id
- * @inode: inode to extract the info from
- * @secid: where result will be saved
- */
-static void smack_inode_getsecid(const struct inode *inode, u32 *secid)
-{
- struct inode_smack *isp = inode->i_security;
-
- *secid = smack_to_secid(isp->smk_inode);
-}
-
-/*
- * File Hooks
- */
-
-/**
- * smack_file_permission - Smack check on file operations
- * @file: unused
- * @mask: unused
- *
- * Returns 0
- *
- * Should access checks be done on each read or write?
- * UNICOS and SELinux say yes.
- * Trusted Solaris, Trusted Irix, and just about everyone else says no.
- *
- * I'll say no for now. Smack does not do the frequent
- * label changing that SELinux does.
- */
-static int smack_file_permission(struct file *file, int mask)
-{
- return 0;
-}
-
-/**
- * smack_file_alloc_security - assign a file security blob
- * @file: the object
- *
- * The security blob for a file is a pointer to the master
- * label list, so no allocation is done.
- *
- * Returns 0
- */
-static int smack_file_alloc_security(struct file *file)
-{
- file->f_security = smk_of_current();
- return 0;
-}
-
-/**
- * smack_file_free_security - clear a file security blob
- * @file: the object
- *
- * The security blob for a file is a pointer to the master
- * label list, so no memory is freed.
- */
-static void smack_file_free_security(struct file *file)
-{
- file->f_security = NULL;
-}
-
-/**
- * smack_file_ioctl - Smack check on ioctls
- * @file: the object
- * @cmd: what to do
- * @arg: unused
- *
- * Relies heavily on the correct use of the ioctl command conventions.
- *
- * Returns 0 if allowed, error code otherwise
- */
-static int smack_file_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- int rc = 0;
- struct smk_audit_info ad;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
- smk_ad_setfield_u_fs_path(&ad, file->f_path);
-
- if (_IOC_DIR(cmd) & _IOC_WRITE)
- rc = smk_curacc(file->f_security, MAY_WRITE, &ad);
-
- if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ))
- rc = smk_curacc(file->f_security, MAY_READ, &ad);
-
- return rc;
-}
-
-/**
- * smack_file_lock - Smack check on file locking
- * @file: the object
- * @cmd: unused
- *
- * Returns 0 if current has write access, error code otherwise
- */
-static int smack_file_lock(struct file *file, unsigned int cmd)
-{
- struct smk_audit_info ad;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
- smk_ad_setfield_u_fs_path(&ad, file->f_path);
- return smk_curacc(file->f_security, MAY_WRITE, &ad);
-}
-
-/**
- * smack_file_fcntl - Smack check on fcntl
- * @file: the object
- * @cmd: what action to check
- * @arg: unused
- *
- * Generally these operations are harmless.
- * File locking operations present an obvious mechanism
- * for passing information, so they require write access.
- *
- * Returns 0 if current has access, error code otherwise
- */
-static int smack_file_fcntl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct smk_audit_info ad;
- int rc = 0;
-
-
- switch (cmd) {
- case F_GETLK:
- case F_SETLK:
- case F_SETLKW:
- case F_SETOWN:
- case F_SETSIG:
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
- smk_ad_setfield_u_fs_path(&ad, file->f_path);
- rc = smk_curacc(file->f_security, MAY_WRITE, &ad);
- break;
- default:
- break;
- }
-
- return rc;
-}
-
-/**
- * smack_file_mmap :
- * Check permissions for a mmap operation. The @file may be NULL, e.g.
- * if mapping anonymous memory.
- * @file contains the file structure for file to map (may be NULL).
- * @reqprot contains the protection requested by the application.
- * @prot contains the protection that will be applied by the kernel.
- * @flags contains the operational flags.
- * Return 0 if permission is granted.
- */
-static int smack_file_mmap(struct file *file,
- unsigned long reqprot, unsigned long prot,
- unsigned long flags, unsigned long addr,
- unsigned long addr_only)
-{
- struct smack_known *skp;
- struct smack_rule *srp;
- struct task_smack *tsp;
- char *sp;
- char *msmack;
- char *osmack;
- struct inode_smack *isp;
- struct dentry *dp;
- int may;
- int mmay;
- int tmay;
- int rc;
-
- /* do DAC check on address space usage */
- rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
- if (rc || addr_only)
- return rc;
-
- if (file == NULL || file->f_dentry == NULL)
- return 0;
-
- dp = file->f_dentry;
-
- if (dp->d_inode == NULL)
- return 0;
-
- isp = dp->d_inode->i_security;
- if (isp->smk_mmap == NULL)
- return 0;
- msmack = isp->smk_mmap;
-
- tsp = current_security();
- sp = smk_of_current();
- skp = smk_find_entry(sp);
- rc = 0;
-
- rcu_read_lock();
- /*
- * For each Smack rule associated with the subject
- * label verify that the SMACK64MMAP also has access
- * to that rule's object label.
- */
- list_for_each_entry_rcu(srp, &skp->smk_rules, list) {
- osmack = srp->smk_object;
- /*
- * Matching labels always allows access.
- */
- if (msmack == osmack)
- continue;
- /*
- * If there is a matching local rule take
- * that into account as well.
- */
- may = smk_access_entry(srp->smk_subject, osmack,
- &tsp->smk_rules);
- if (may == -ENOENT)
- may = srp->smk_access;
- else
- may &= srp->smk_access;
- /*
- * If may is zero the SMACK64MMAP subject can't
- * possibly have less access.
- */
- if (may == 0)
- continue;
-
- /*
- * Fetch the global list entry.
- * If there isn't one a SMACK64MMAP subject
- * can't have as much access as current.
- */
- skp = smk_find_entry(msmack);
- mmay = smk_access_entry(msmack, osmack, &skp->smk_rules);
- if (mmay == -ENOENT) {
- rc = -EACCES;
- break;
- }
- /*
- * If there is a local entry it modifies the
- * potential access, too.
- */
- tmay = smk_access_entry(msmack, osmack, &tsp->smk_rules);
- if (tmay != -ENOENT)
- mmay &= tmay;
-
- /*
- * If there is any access available to current that is
- * not available to a SMACK64MMAP subject
- * deny access.
- */
- if ((may | mmay) != mmay) {
- rc = -EACCES;
- break;
- }
- }
-
- rcu_read_unlock();
-
- return rc;
-}
-
-/**
- * smack_file_set_fowner - set the file security blob value
- * @file: object in question
- *
- * Returns 0
- * Further research may be required on this one.
- */
-static int smack_file_set_fowner(struct file *file)
-{
- file->f_security = smk_of_current();
- return 0;
-}
-
-/**
- * smack_file_send_sigiotask - Smack on sigio
- * @tsk: The target task
- * @fown: the object the signal come from
- * @signum: unused
- *
- * Allow a privileged task to get signals even if it shouldn't
- *
- * Returns 0 if a subject with the object's smack could
- * write to the task, an error code otherwise.
- */
-static int smack_file_send_sigiotask(struct task_struct *tsk,
- struct fown_struct *fown, int signum)
-{
- struct file *file;
- int rc;
- char *tsp = smk_of_task(tsk->cred->security);
- struct smk_audit_info ad;
-
- /*
- * struct fown_struct is never outside the context of a struct file
- */
- file = container_of(fown, struct file, f_owner);
-
- /* we don't log here as rc can be overriden */
- rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL);
- if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
- rc = 0;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
- smk_ad_setfield_u_tsk(&ad, tsk);
- smack_log(file->f_security, tsp, MAY_WRITE, rc, &ad);
- return rc;
-}
-
-/**
- * smack_file_receive - Smack file receive check
- * @file: the object
- *
- * Returns 0 if current has access, error code otherwise
- */
-static int smack_file_receive(struct file *file)
-{
- int may = 0;
- struct smk_audit_info ad;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
- smk_ad_setfield_u_fs_path(&ad, file->f_path);
- /*
- * This code relies on bitmasks.
- */
- if (file->f_mode & FMODE_READ)
- may = MAY_READ;
- if (file->f_mode & FMODE_WRITE)
- may |= MAY_WRITE;
-
- return smk_curacc(file->f_security, may, &ad);
-}
-
-/**
- * smack_dentry_open - Smack dentry open processing
- * @file: the object
- * @cred: unused
- *
- * Set the security blob in the file structure.
- *
- * Returns 0
- */
-static int smack_dentry_open(struct file *file, const struct cred *cred)
-{
- struct inode_smack *isp = file->f_path.dentry->d_inode->i_security;
-
- file->f_security = isp->smk_inode;
-
- return 0;
-}
-
-/*
- * Task hooks
- */
-
-/**
- * smack_cred_alloc_blank - "allocate" blank task-level security credentials
- * @new: the new credentials
- * @gfp: the atomicity of any memory allocations
- *
- * Prepare a blank set of credentials for modification. This must allocate all
- * the memory the LSM module might require such that cred_transfer() can
- * complete without error.
- */
-static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
-{
- struct task_smack *tsp;
-
- tsp = new_task_smack(NULL, NULL, gfp);
- if (tsp == NULL)
- return -ENOMEM;
-
- cred->security = tsp;
-
- return 0;
-}
-
-
-/**
- * smack_cred_free - "free" task-level security credentials
- * @cred: the credentials in question
- *
- */
-static void smack_cred_free(struct cred *cred)
-{
- struct task_smack *tsp = cred->security;
- struct smack_rule *rp;
- struct list_head *l;
- struct list_head *n;
-
- if (tsp == NULL)
- return;
- cred->security = NULL;
-
- list_for_each_safe(l, n, &tsp->smk_rules) {
- rp = list_entry(l, struct smack_rule, list);
- list_del(&rp->list);
- kfree(rp);
- }
- kfree(tsp);
-}
-
-/**
- * smack_cred_prepare - prepare new set of credentials for modification
- * @new: the new credentials
- * @old: the original credentials
- * @gfp: the atomicity of any memory allocations
- *
- * Prepare a new set of credentials for modification.
- */
-static int smack_cred_prepare(struct cred *new, const struct cred *old,
- gfp_t gfp)
-{
- struct task_smack *old_tsp = old->security;
- struct task_smack *new_tsp;
- int rc;
-
- new_tsp = new_task_smack(old_tsp->smk_task, old_tsp->smk_task, gfp);
- if (new_tsp == NULL)
- return -ENOMEM;
-
- rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp);
- if (rc != 0)
- return rc;
-
- new->security = new_tsp;
- return 0;
-}
-
-/**
- * smack_cred_transfer - Transfer the old credentials to the new credentials
- * @new: the new credentials
- * @old: the original credentials
- *
- * Fill in a set of blank credentials from another set of credentials.
- */
-static void smack_cred_transfer(struct cred *new, const struct cred *old)
-{
- struct task_smack *old_tsp = old->security;
- struct task_smack *new_tsp = new->security;
-
- new_tsp->smk_task = old_tsp->smk_task;
- new_tsp->smk_forked = old_tsp->smk_task;
- mutex_init(&new_tsp->smk_rules_lock);
- INIT_LIST_HEAD(&new_tsp->smk_rules);
-
-
- /* cbs copy rule list */
-}
-
-/**
- * smack_kernel_act_as - Set the subjective context in a set of credentials
- * @new: points to the set of credentials to be modified.
- * @secid: specifies the security ID to be set
- *
- * Set the security data for a kernel service.
- */
-static int smack_kernel_act_as(struct cred *new, u32 secid)
-{
- struct task_smack *new_tsp = new->security;
- char *smack = smack_from_secid(secid);
-
- if (smack == NULL)
- return -EINVAL;
-
- new_tsp->smk_task = smack;
- return 0;
-}
-
-/**
- * smack_kernel_create_files_as - Set the file creation label in a set of creds
- * @new: points to the set of credentials to be modified
- * @inode: points to the inode to use as a reference
- *
- * Set the file creation context in a set of credentials to the same
- * as the objective context of the specified inode
- */
-static int smack_kernel_create_files_as(struct cred *new,
- struct inode *inode)
-{
- struct inode_smack *isp = inode->i_security;
- struct task_smack *tsp = new->security;
-
- tsp->smk_forked = isp->smk_inode;
- tsp->smk_task = isp->smk_inode;
- return 0;
-}
-
-/**
- * smk_curacc_on_task - helper to log task related access
- * @p: the task object
- * @access: the access requested
- * @caller: name of the calling function for audit
- *
- * Return 0 if access is permitted
- */
-static int smk_curacc_on_task(struct task_struct *p, int access,
- const char *caller)
-{
- struct smk_audit_info ad;
-
- smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK);
- smk_ad_setfield_u_tsk(&ad, p);
- return smk_curacc(smk_of_task(task_security(p)), access, &ad);
-}
-
-/**
- * smack_task_setpgid - Smack check on setting pgid
- * @p: the task object
- * @pgid: unused
- *
- * Return 0 if write access is permitted
- */
-static int smack_task_setpgid(struct task_struct *p, pid_t pgid)
-{
- return smk_curacc_on_task(p, MAY_WRITE, __func__);
-}
-
-/**
- * smack_task_getpgid - Smack access check for getpgid
- * @p: the object task
- *
- * Returns 0 if current can read the object task, error code otherwise
- */
-static int smack_task_getpgid(struct task_struct *p)
-{
- return smk_curacc_on_task(p, MAY_READ, __func__);
-}
-
-/**
- * smack_task_getsid - Smack access check for getsid
- * @p: the object task
- *
- * Returns 0 if current can read the object task, error code otherwise
- */
-static int smack_task_getsid(struct task_struct *p)
-{
- return smk_curacc_on_task(p, MAY_READ, __func__);
-}
-
-/**
- * smack_task_getsecid - get the secid of the task
- * @p: the object task
- * @secid: where to put the result
- *
- * Sets the secid to contain a u32 version of the smack label.
- */
-static void smack_task_getsecid(struct task_struct *p, u32 *secid)
-{
- *secid = smack_to_secid(smk_of_task(task_security(p)));
-}
-
-/**
- * smack_task_setnice - Smack check on setting nice
- * @p: the task object
- * @nice: unused
- *
- * Return 0 if write access is permitted
- */
-static int smack_task_setnice(struct task_struct *p, int nice)
-{
- int rc;
-
- rc = cap_task_setnice(p, nice);
- if (rc == 0)
- rc = smk_curacc_on_task(p, MAY_WRITE, __func__);
- return rc;
-}
-
-/**
- * smack_task_setioprio - Smack check on setting ioprio
- * @p: the task object
- * @ioprio: unused
- *
- * Return 0 if write access is permitted
- */
-static int smack_task_setioprio(struct task_struct *p, int ioprio)
-{
- int rc;
-
- rc = cap_task_setioprio(p, ioprio);
- if (rc == 0)
- rc = smk_curacc_on_task(p, MAY_WRITE, __func__);
- return rc;
-}
-
-/**
- * smack_task_getioprio - Smack check on reading ioprio
- * @p: the task object
- *
- * Return 0 if read access is permitted
- */
-static int smack_task_getioprio(struct task_struct *p)
-{
- return smk_curacc_on_task(p, MAY_READ, __func__);
-}
-
-/**
- * smack_task_setscheduler - Smack check on setting scheduler
- * @p: the task object
- * @policy: unused
- * @lp: unused
- *
- * Return 0 if read access is permitted
- */
-static int smack_task_setscheduler(struct task_struct *p)
-{
- int rc;
-
- rc = cap_task_setscheduler(p);
- if (rc == 0)
- rc = smk_curacc_on_task(p, MAY_WRITE, __func__);
- return rc;
-}
-
-/**
- * smack_task_getscheduler - Smack check on reading scheduler
- * @p: the task object
- *
- * Return 0 if read access is permitted
- */
-static int smack_task_getscheduler(struct task_struct *p)
-{
- return smk_curacc_on_task(p, MAY_READ, __func__);
-}
-
-/**
- * smack_task_movememory - Smack check on moving memory
- * @p: the task object
- *
- * Return 0 if write access is permitted
- */
-static int smack_task_movememory(struct task_struct *p)
-{
- return smk_curacc_on_task(p, MAY_WRITE, __func__);
-}
-
-/**
- * smack_task_kill - Smack check on signal delivery
- * @p: the task object
- * @info: unused
- * @sig: unused
- * @secid: identifies the smack to use in lieu of current's
- *
- * Return 0 if write access is permitted
- *
- * The secid behavior is an artifact of an SELinux hack
- * in the USB code. Someday it may go away.
- */
-static int smack_task_kill(struct task_struct *p, struct siginfo *info,
- int sig, u32 secid)
-{
- struct smk_audit_info ad;
-
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
- smk_ad_setfield_u_tsk(&ad, p);
- /*
- * Sending a signal requires that the sender
- * can write the receiver.
- */
- if (secid == 0)
- return smk_curacc(smk_of_task(task_security(p)), MAY_WRITE,
- &ad);
- /*
- * If the secid isn't 0 we're dealing with some USB IO
- * specific behavior. This is not clean. For one thing
- * we can't take privilege into account.
- */
- return smk_access(smack_from_secid(secid),
- smk_of_task(task_security(p)), MAY_WRITE, &ad);
-}
-
-/**
- * smack_task_wait - Smack access check for waiting
- * @p: task to wait for
- *
- * Returns 0 if current can wait for p, error code otherwise
- */
-static int smack_task_wait(struct task_struct *p)
-{
- struct smk_audit_info ad;
- char *sp = smk_of_current();
- char *tsp = smk_of_forked(task_security(p));
- int rc;
-
- /* we don't log here, we can be overriden */
- rc = smk_access(tsp, sp, MAY_WRITE, NULL);
- if (rc == 0)
- goto out_log;
-
- /*
- * Allow the operation to succeed if either task
- * has privilege to perform operations that might
- * account for the smack labels having gotten to
- * be different in the first place.
- *
- * This breaks the strict subject/object access
- * control ideal, taking the object's privilege
- * state into account in the decision as well as
- * the smack value.
- */
- if (capable(CAP_MAC_OVERRIDE) || has_capability(p, CAP_MAC_OVERRIDE))
- rc = 0;
- /* we log only if we didn't get overriden */
- out_log:
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
- smk_ad_setfield_u_tsk(&ad, p);
- smack_log(tsp, sp, MAY_WRITE, rc, &ad);
- return rc;
-}
-
-/**
- * smack_task_to_inode - copy task smack into the inode blob
- * @p: task to copy from
- * @inode: inode to copy to
- *
- * Sets the smack pointer in the inode security blob
- */
-static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
-{
- struct inode_smack *isp = inode->i_security;
- isp->smk_inode = smk_of_task(task_security(p));
-}
-
-/*
- * Socket hooks.
- */
-
-/**
- * smack_sk_alloc_security - Allocate a socket blob
- * @sk: the socket
- * @family: unused
- * @gfp_flags: memory allocation flags
- *
- * Assign Smack pointers to current
- *
- * Returns 0 on success, -ENOMEM is there's no memory
- */
-static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
-{
- char *csp = smk_of_current();
- struct socket_smack *ssp;
-
- ssp = kzalloc(sizeof(struct socket_smack), gfp_flags);
- if (ssp == NULL)
- return -ENOMEM;
-
- ssp->smk_in = csp;
- ssp->smk_out = csp;
- ssp->smk_packet = NULL;
-
- sk->sk_security = ssp;
-
- return 0;
-}
-
-/**
- * smack_sk_free_security - Free a socket blob
- * @sk: the socket
- *
- * Clears the blob pointer
- */
-static void smack_sk_free_security(struct sock *sk)
-{
- kfree(sk->sk_security);
-}
-
-/**
-* smack_host_label - check host based restrictions
-* @sip: the object end
-*
-* looks for host based access restrictions
-*
-* This version will only be appropriate for really small sets of single label
-* hosts. The caller is responsible for ensuring that the RCU read lock is
-* taken before calling this function.
-*
-* Returns the label of the far end or NULL if it's not special.
-*/
-static char *smack_host_label(struct sockaddr_in *sip)
-{
- struct smk_netlbladdr *snp;
- struct in_addr *siap = &sip->sin_addr;
-
- if (siap->s_addr == 0)
- return NULL;
-
- list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list)
- /*
- * we break after finding the first match because
- * the list is sorted from longest to shortest mask
- * so we have found the most specific match
- */
- if ((&snp->smk_host.sin_addr)->s_addr ==
- (siap->s_addr & (&snp->smk_mask)->s_addr)) {
- /* we have found the special CIPSO option */
- if (snp->smk_label == smack_cipso_option)
- return NULL;
- return snp->smk_label;
- }
-
- return NULL;
-}
-
-/**
- * smack_set_catset - convert a capset to netlabel mls categories
- * @catset: the Smack categories
- * @sap: where to put the netlabel categories
- *
- * Allocates and fills attr.mls.cat
- */
-static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap)
-{
- unsigned char *cp;
- unsigned char m;
- int cat;
- int rc;
- int byte;
-
- if (!catset)
- return;
-
- sap->flags |= NETLBL_SECATTR_MLS_CAT;
- sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
- sap->attr.mls.cat->startbit = 0;
-
- for (cat = 1, cp = catset, byte = 0; byte < SMK_LABELLEN; cp++, byte++)
- for (m = 0x80; m != 0; m >>= 1, cat++) {
- if ((m & *cp) == 0)
- continue;
- rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
- cat, GFP_ATOMIC);
- }
-}
-
-/**
- * smack_to_secattr - fill a secattr from a smack value
- * @smack: the smack value
- * @nlsp: where the result goes
- *
- * Casey says that CIPSO is good enough for now.
- * It can be used to effect.
- * It can also be abused to effect when necessary.
- * Apologies to the TSIG group in general and GW in particular.
- */
-static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
-{
- struct smack_cipso cipso;
- int rc;
-
- nlsp->domain = smack;
- nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
-
- rc = smack_to_cipso(smack, &cipso);
- if (rc == 0) {
- nlsp->attr.mls.lvl = cipso.smk_level;
- smack_set_catset(cipso.smk_catset, nlsp);
- } else {
- nlsp->attr.mls.lvl = smack_cipso_direct;
- smack_set_catset(smack, nlsp);
- }
-}
-
-/**
- * smack_netlabel - Set the secattr on a socket
- * @sk: the socket
- * @labeled: socket label scheme
- *
- * Convert the outbound smack value (smk_out) to a
- * secattr and attach it to the socket.
- *
- * Returns 0 on success or an error code
- */
-static int smack_netlabel(struct sock *sk, int labeled)
-{
- struct socket_smack *ssp = sk->sk_security;
- struct netlbl_lsm_secattr secattr;
- int rc = 0;
-
- /*
- * Usually the netlabel code will handle changing the
- * packet labeling based on the label.
- * The case of a single label host is different, because
- * a single label host should never get a labeled packet
- * even though the label is usually associated with a packet
- * label.
- */
- local_bh_disable();
- bh_lock_sock_nested(sk);
-
- if (ssp->smk_out == smack_net_ambient ||
- labeled == SMACK_UNLABELED_SOCKET)
- netlbl_sock_delattr(sk);
- else {
- netlbl_secattr_init(&secattr);
- smack_to_secattr(ssp->smk_out, &secattr);
- rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr);
- netlbl_secattr_destroy(&secattr);
- }
-
- bh_unlock_sock(sk);
- local_bh_enable();
-
- return rc;
-}
-
-/**
- * smack_netlbel_send - Set the secattr on a socket and perform access checks
- * @sk: the socket
- * @sap: the destination address
- *
- * Set the correct secattr for the given socket based on the destination
- * address and perform any outbound access checks needed.
- *
- * Returns 0 on success or an error code.
- *
- */
-static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
-{
- int rc;
- int sk_lbl;
- char *hostsp;
- struct socket_smack *ssp = sk->sk_security;
- struct smk_audit_info ad;
-
- rcu_read_lock();
- hostsp = smack_host_label(sap);
- if (hostsp != NULL) {
-#ifdef CONFIG_AUDIT
- struct lsm_network_audit net;
-
- smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
- ad.a.u.net->family = sap->sin_family;
- ad.a.u.net->dport = sap->sin_port;
- ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr;
-#endif
- sk_lbl = SMACK_UNLABELED_SOCKET;
- rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad);
- } else {
- sk_lbl = SMACK_CIPSO_SOCKET;
- rc = 0;
- }
- rcu_read_unlock();
- if (rc != 0)
- return rc;
-
- return smack_netlabel(sk, sk_lbl);
-}
-
-/**
- * smack_inode_setsecurity - set smack xattrs
- * @inode: the object
- * @name: attribute name
- * @value: attribute value
- * @size: size of the attribute
- * @flags: unused
- *
- * Sets the named attribute in the appropriate blob
- *
- * Returns 0 on success, or an error code
- */
-static int smack_inode_setsecurity(struct inode *inode, const char *name,
- const void *value, size_t size, int flags)
-{
- char *sp;
- struct inode_smack *nsp = inode->i_security;
- struct socket_smack *ssp;
- struct socket *sock;
- int rc = 0;
-
- if (value == NULL || size > SMK_LABELLEN || size == 0)
- return -EACCES;
-
- sp = smk_import(value, size);
- if (sp == NULL)
- return -EINVAL;
-
- if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
- nsp->smk_inode = sp;
- nsp->smk_flags |= SMK_INODE_INSTANT;
- return 0;
- }
- /*
- * The rest of the Smack xattrs are only on sockets.
- */
- if (inode->i_sb->s_magic != SOCKFS_MAGIC)
- return -EOPNOTSUPP;
-
- sock = SOCKET_I(inode);
- if (sock == NULL || sock->sk == NULL)
- return -EOPNOTSUPP;
-
- ssp = sock->sk->sk_security;
-
- if (strcmp(name, XATTR_SMACK_IPIN) == 0)
- ssp->smk_in = sp;
- else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
- ssp->smk_out = sp;
- if (sock->sk->sk_family != PF_UNIX) {
- rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
- if (rc != 0)
- printk(KERN_WARNING
- "Smack: \"%s\" netlbl error %d.\n",
- __func__, -rc);
- }
- } else
- return -EOPNOTSUPP;
-
- return 0;
-}
-
-/**
- * smack_socket_post_create - finish socket setup
- * @sock: the socket
- * @family: protocol family
- * @type: unused
- * @protocol: unused
- * @kern: unused
- *
- * Sets the netlabel information on the socket
- *
- * Returns 0 on success, and error code otherwise
- */
-static int smack_socket_post_create(struct socket *sock, int family,
- int type, int protocol, int kern)
-{
- if (family != PF_INET || sock->sk == NULL)
- return 0;
- /*
- * Set the outbound netlbl.
- */
- return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
-}
-
-/**
- * smack_socket_connect - connect access check
- * @sock: the socket
- * @sap: the other end
- * @addrlen: size of sap
- *
- * Verifies that a connection may be possible
- *
- * Returns 0 on success, and error code otherwise
- */
-static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
- int addrlen)
-{
- if (sock->sk == NULL || sock->sk->sk_family != PF_INET)
- return 0;
- if (addrlen < sizeof(struct sockaddr_in))
- return -EINVAL;
-
- return smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap);
-}
-
-/**
- * smack_flags_to_may - convert S_ to MAY_ values
- * @flags: the S_ value
- *
- * Returns the equivalent MAY_ value
- */
-static int smack_flags_to_may(int flags)
-{
- int may = 0;
-
- if (flags & S_IRUGO)
- may |= MAY_READ;
- if (flags & S_IWUGO)
- may |= MAY_WRITE;
- if (flags & S_IXUGO)
- may |= MAY_EXEC;
-
- return may;
-}
-
-/**
- * smack_msg_msg_alloc_security - Set the security blob for msg_msg
- * @msg: the object
- *
- * Returns 0
- */
-static int smack_msg_msg_alloc_security(struct msg_msg *msg)
-{
- msg->security = smk_of_current();
- return 0;
-}
-
-/**
- * smack_msg_msg_free_security - Clear the security blob for msg_msg
- * @msg: the object
- *
- * Clears the blob pointer
- */
-static void smack_msg_msg_free_security(struct msg_msg *msg)
-{
- msg->security = NULL;
-}
-
-/**
- * smack_of_shm - the smack pointer for the shm
- * @shp: the object
- *
- * Returns a pointer to the smack value
- */
-static char *smack_of_shm(struct shmid_kernel *shp)
-{
- return (char *)shp->shm_perm.security;
-}
-
-/**
- * smack_shm_alloc_security - Set the security blob for shm
- * @shp: the object
- *
- * Returns 0
- */
-static int smack_shm_alloc_security(struct shmid_kernel *shp)
-{
- struct kern_ipc_perm *isp = &shp->shm_perm;
-
- isp->security = smk_of_current();
- return 0;
-}
-
-/**
- * smack_shm_free_security - Clear the security blob for shm
- * @shp: the object
- *
- * Clears the blob pointer
- */
-static void smack_shm_free_security(struct shmid_kernel *shp)
-{
- struct kern_ipc_perm *isp = &shp->shm_perm;
-
- isp->security = NULL;
-}
-
-/**
- * smk_curacc_shm : check if current has access on shm
- * @shp : the object
- * @access : access requested
- *
- * Returns 0 if current has the requested access, error code otherwise
- */
-static int smk_curacc_shm(struct shmid_kernel *shp, int access)
-{
- char *ssp = smack_of_shm(shp);
- struct smk_audit_info ad;
-
-#ifdef CONFIG_AUDIT
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
- ad.a.u.ipc_id = shp->shm_perm.id;
-#endif
- return smk_curacc(ssp, access, &ad);
-}
-
-/**
- * smack_shm_associate - Smack access check for shm
- * @shp: the object
- * @shmflg: access requested
- *
- * Returns 0 if current has the requested access, error code otherwise
- */
-static int smack_shm_associate(struct shmid_kernel *shp, int shmflg)
-{
- int may;
-
- may = smack_flags_to_may(shmflg);
- return smk_curacc_shm(shp, may);
-}
-
-/**
- * smack_shm_shmctl - Smack access check for shm
- * @shp: the object
- * @cmd: what it wants to do
- *
- * Returns 0 if current has the requested access, error code otherwise
- */
-static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
-{
- int may;
-
- switch (cmd) {
- case IPC_STAT:
- case SHM_STAT:
- may = MAY_READ;
- break;
- case IPC_SET:
- case SHM_LOCK:
- case SHM_UNLOCK:
- case IPC_RMID:
- may = MAY_READWRITE;
- break;
- case IPC_INFO:
- case SHM_INFO:
- /*
- * System level information.
- */
- return 0;
- default:
- return -EINVAL;
- }
- return smk_curacc_shm(shp, may);
-}
-
-/**
- * smack_shm_shmat - Smack access for shmat
- * @shp: the object
- * @shmaddr: unused
- * @shmflg: access requested
- *
- * Returns 0 if current has the requested access, error code otherwise
- */
-static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
- int shmflg)
-{
- int may;
-
- may = smack_flags_to_may(shmflg);
- return smk_curacc_shm(shp, may);
-}
-
-/**
- * smack_of_sem - the smack pointer for the sem
- * @sma: the object
- *
- * Returns a pointer to the smack value
- */
-static char *smack_of_sem(struct sem_array *sma)
-{
- return (char *)sma->sem_perm.security;
-}
-
-/**
- * smack_sem_alloc_security - Set the security blob for sem
- * @sma: the object
- *
- * Returns 0
- */
-static int smack_sem_alloc_security(struct sem_array *sma)
-{
- struct kern_ipc_perm *isp = &sma->sem_perm;
-
- isp->security = smk_of_current();
- return 0;
-}
-
-/**
- * smack_sem_free_security - Clear the security blob for sem
- * @sma: the object
- *
- * Clears the blob pointer
- */
-static void smack_sem_free_security(struct sem_array *sma)
-{
- struct kern_ipc_perm *isp = &sma->sem_perm;
-
- isp->security = NULL;
-}
-
-/**
- * smk_curacc_sem : check if current has access on sem
- * @sma : the object
- * @access : access requested
- *
- * Returns 0 if current has the requested access, error code otherwise
- */
-static int smk_curacc_sem(struct sem_array *sma, int access)
-{
- char *ssp = smack_of_sem(sma);
- struct smk_audit_info ad;
-
-#ifdef CONFIG_AUDIT
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
- ad.a.u.ipc_id = sma->sem_perm.id;
-#endif
- return smk_curacc(ssp, access, &ad);
-}
-
-/**
- * smack_sem_associate - Smack access check for sem
- * @sma: the object
- * @semflg: access requested
- *
- * Returns 0 if current has the requested access, error code otherwise
- */
-static int smack_sem_associate(struct sem_array *sma, int semflg)
-{
- int may;
-
- may = smack_flags_to_may(semflg);
- return smk_curacc_sem(sma, may);
-}
-
-/**
- * smack_sem_shmctl - Smack access check for sem
- * @sma: the object
- * @cmd: what it wants to do
- *
- * Returns 0 if current has the requested access, error code otherwise
- */
-static int smack_sem_semctl(struct sem_array *sma, int cmd)
-{
- int may;
-
- switch (cmd) {
- case GETPID:
- case GETNCNT:
- case GETZCNT:
- case GETVAL:
- case GETALL:
- case IPC_STAT:
- case SEM_STAT:
- may = MAY_READ;
- break;
- case SETVAL:
- case SETALL:
- case IPC_RMID:
- case IPC_SET:
- may = MAY_READWRITE;
- break;
- case IPC_INFO:
- case SEM_INFO:
- /*
- * System level information
- */
- return 0;
- default:
- return -EINVAL;
- }
-
- return smk_curacc_sem(sma, may);
-}
-
-/**
- * smack_sem_semop - Smack checks of semaphore operations
- * @sma: the object
- * @sops: unused
- * @nsops: unused
- * @alter: unused
- *
- * Treated as read and write in all cases.
- *
- * Returns 0 if access is allowed, error code otherwise
- */
-static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops,
- unsigned nsops, int alter)
-{
- return smk_curacc_sem(sma, MAY_READWRITE);
-}
-
-/**
- * smack_msg_alloc_security - Set the security blob for msg
- * @msq: the object
- *
- * Returns 0
- */
-static int smack_msg_queue_alloc_security(struct msg_queue *msq)
-{
- struct kern_ipc_perm *kisp = &msq->q_perm;
-
- kisp->security = smk_of_current();
- return 0;
-}
-
-/**
- * smack_msg_free_security - Clear the security blob for msg
- * @msq: the object
- *
- * Clears the blob pointer
- */
-static void smack_msg_queue_free_security(struct msg_queue *msq)
-{
- struct kern_ipc_perm *kisp = &msq->q_perm;
-
- kisp->security = NULL;
-}
-
-/**
- * smack_of_msq - the smack pointer for the msq
- * @msq: the object
- *
- * Returns a pointer to the smack value
- */
-static char *smack_of_msq(struct msg_queue *msq)
-{
- return (char *)msq->q_perm.security;
-}
-
-/**
- * smk_curacc_msq : helper to check if current has access on msq
- * @msq : the msq
- * @access : access requested
- *
- * return 0 if current has access, error otherwise
- */
-static int smk_curacc_msq(struct msg_queue *msq, int access)
-{
- char *msp = smack_of_msq(msq);
- struct smk_audit_info ad;
-
-#ifdef CONFIG_AUDIT
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
- ad.a.u.ipc_id = msq->q_perm.id;
-#endif
- return smk_curacc(msp, access, &ad);
-}
-
-/**
- * smack_msg_queue_associate - Smack access check for msg_queue
- * @msq: the object
- * @msqflg: access requested
- *
- * Returns 0 if current has the requested access, error code otherwise
- */
-static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg)
-{
- int may;
-
- may = smack_flags_to_may(msqflg);
- return smk_curacc_msq(msq, may);
-}
-
-/**
- * smack_msg_queue_msgctl - Smack access check for msg_queue
- * @msq: the object
- * @cmd: what it wants to do
- *
- * Returns 0 if current has the requested access, error code otherwise
- */
-static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
-{
- int may;
-
- switch (cmd) {
- case IPC_STAT:
- case MSG_STAT:
- may = MAY_READ;
- break;
- case IPC_SET:
- case IPC_RMID:
- may = MAY_READWRITE;
- break;
- case IPC_INFO:
- case MSG_INFO:
- /*
- * System level information
- */
- return 0;
- default:
- return -EINVAL;
- }
-
- return smk_curacc_msq(msq, may);
-}
-
-/**
- * smack_msg_queue_msgsnd - Smack access check for msg_queue
- * @msq: the object
- * @msg: unused
- * @msqflg: access requested
- *
- * Returns 0 if current has the requested access, error code otherwise
- */
-static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
- int msqflg)
-{
- int may;
-
- may = smack_flags_to_may(msqflg);
- return smk_curacc_msq(msq, may);
-}
-
-/**
- * smack_msg_queue_msgsnd - Smack access check for msg_queue
- * @msq: the object
- * @msg: unused
- * @target: unused
- * @type: unused
- * @mode: unused
- *
- * Returns 0 if current has read and write access, error code otherwise
- */
-static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
- struct task_struct *target, long type, int mode)
-{
- return smk_curacc_msq(msq, MAY_READWRITE);
-}
-
-/**
- * smack_ipc_permission - Smack access for ipc_permission()
- * @ipp: the object permissions
- * @flag: access requested
- *
- * Returns 0 if current has read and write access, error code otherwise
- */
-static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
-{
- char *isp = ipp->security;
- int may = smack_flags_to_may(flag);
- struct smk_audit_info ad;
-
-#ifdef CONFIG_AUDIT
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
- ad.a.u.ipc_id = ipp->id;
-#endif
- return smk_curacc(isp, may, &ad);
-}
-
-/**
- * smack_ipc_getsecid - Extract smack security id
- * @ipp: the object permissions
- * @secid: where result will be saved
- */
-static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid)
-{
- char *smack = ipp->security;
-
- *secid = smack_to_secid(smack);
-}
-
-/**
- * smack_d_instantiate - Make sure the blob is correct on an inode
- * @opt_dentry: dentry where inode will be attached
- * @inode: the object
- *
- * Set the inode's security blob if it hasn't been done already.
- */
-static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
-{
- struct super_block *sbp;
- struct superblock_smack *sbsp;
- struct inode_smack *isp;
- char *csp = smk_of_current();
- char *fetched;
- char *final;
- char trattr[TRANS_TRUE_SIZE];
- int transflag = 0;
- struct dentry *dp;
-
- if (inode == NULL)
- return;
-
- isp = inode->i_security;
-
- mutex_lock(&isp->smk_lock);
- /*
- * If the inode is already instantiated
- * take the quick way out
- */
- if (isp->smk_flags & SMK_INODE_INSTANT)
- goto unlockandout;
-
- sbp = inode->i_sb;
- sbsp = sbp->s_security;
- /*
- * We're going to use the superblock default label
- * if there's no label on the file.
- */
- final = sbsp->smk_default;
-
- /*
- * If this is the root inode the superblock
- * may be in the process of initialization.
- * If that is the case use the root value out
- * of the superblock.
- */
- if (opt_dentry->d_parent == opt_dentry) {
- isp->smk_inode = sbsp->smk_root;
- isp->smk_flags |= SMK_INODE_INSTANT;
- goto unlockandout;
- }
-
- /*
- * This is pretty hackish.
- * Casey says that we shouldn't have to do
- * file system specific code, but it does help
- * with keeping it simple.
- */
- switch (sbp->s_magic) {
- case SMACK_MAGIC:
- /*
- * Casey says that it's a little embarrassing
- * that the smack file system doesn't do
- * extended attributes.
- */
- final = smack_known_star.smk_known;
- break;
- case PIPEFS_MAGIC:
- /*
- * Casey says pipes are easy (?)
- */
- final = smack_known_star.smk_known;
- break;
- case DEVPTS_SUPER_MAGIC:
- /*
- * devpts seems content with the label of the task.
- * Programs that change smack have to treat the
- * pty with respect.
- */
- final = csp;
- break;
- case SOCKFS_MAGIC:
- /*
- * Socket access is controlled by the socket
- * structures associated with the task involved.
- */
- final = smack_known_star.smk_known;
- break;
- case PROC_SUPER_MAGIC:
- /*
- * Casey says procfs appears not to care.
- * The superblock default suffices.
- */
- break;
- case TMPFS_MAGIC:
- /*
- * Device labels should come from the filesystem,
- * but watch out, because they're volitile,
- * getting recreated on every reboot.
- */
- final = smack_known_star.smk_known;
- /*
- * No break.
- *
- * If a smack value has been set we want to use it,
- * but since tmpfs isn't giving us the opportunity
- * to set mount options simulate setting the
- * superblock default.
- */
- default:
- /*
- * This isn't an understood special case.
- * Get the value from the xattr.
- */
-
- /*
- * UNIX domain sockets use lower level socket data.
- */
- if (S_ISSOCK(inode->i_mode)) {
- final = smack_known_star.smk_known;
- break;
- }
- /*
- * No xattr support means, alas, no SMACK label.
- * Use the aforeapplied default.
- * It would be curious if the label of the task
- * does not match that assigned.
- */
- if (inode->i_op->getxattr == NULL)
- break;
- /*
- * Get the dentry for xattr.
- */
- dp = dget(opt_dentry);
- fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp);
- if (fetched != NULL) {
- final = fetched;
- if (S_ISDIR(inode->i_mode)) {
- trattr[0] = '\0';
- inode->i_op->getxattr(dp,
- XATTR_NAME_SMACKTRANSMUTE,
- trattr, TRANS_TRUE_SIZE);
- if (strncmp(trattr, TRANS_TRUE,
- TRANS_TRUE_SIZE) == 0)
- transflag = SMK_INODE_TRANSMUTE;
- }
- }
- isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
- isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
-
- dput(dp);
- break;
- }
-
- if (final == NULL)
- isp->smk_inode = csp;
- else
- isp->smk_inode = final;
-
- isp->smk_flags |= (SMK_INODE_INSTANT | transflag);
-
-unlockandout:
- mutex_unlock(&isp->smk_lock);
- return;
-}
-
-/**
- * smack_getprocattr - Smack process attribute access
- * @p: the object task
- * @name: the name of the attribute in /proc/.../attr
- * @value: where to put the result
- *
- * Places a copy of the task Smack into value
- *
- * Returns the length of the smack label or an error code
- */
-static int smack_getprocattr(struct task_struct *p, char *name, char **value)
-{
- char *cp;
- int slen;
-
- if (strcmp(name, "current") != 0)
- return -EINVAL;
-
- cp = kstrdup(smk_of_task(task_security(p)), GFP_KERNEL);
- if (cp == NULL)
- return -ENOMEM;
-
- slen = strlen(cp);
- *value = cp;
- return slen;
-}
-
-/**
- * smack_setprocattr - Smack process attribute setting
- * @p: the object task
- * @name: the name of the attribute in /proc/.../attr
- * @value: the value to set
- * @size: the size of the value
- *
- * Sets the Smack value of the task. Only setting self
- * is permitted and only with privilege
- *
- * Returns the length of the smack label or an error code
- */
-static int smack_setprocattr(struct task_struct *p, char *name,
- void *value, size_t size)
-{
- int rc;
- struct task_smack *tsp;
- struct task_smack *oldtsp;
- struct cred *new;
- char *newsmack;
-
- /*
- * Changing another process' Smack value is too dangerous
- * and supports no sane use case.
- */
- if (p != current)
- return -EPERM;
-
- if (!capable(CAP_MAC_ADMIN))
- return -EPERM;
-
- if (value == NULL || size == 0 || size >= SMK_LABELLEN)
- return -EINVAL;
-
- if (strcmp(name, "current") != 0)
- return -EINVAL;
-
- newsmack = smk_import(value, size);
- if (newsmack == NULL)
- return -EINVAL;
-
- /*
- * No process is ever allowed the web ("@") label.
- */
- if (newsmack == smack_known_web.smk_known)
- return -EPERM;
-
- oldtsp = p->cred->security;
- new = prepare_creds();
- if (new == NULL)
- return -ENOMEM;
-
- tsp = new_task_smack(newsmack, oldtsp->smk_forked, GFP_KERNEL);
- if (tsp == NULL) {
- kfree(new);
- return -ENOMEM;
- }
- rc = smk_copy_rules(&tsp->smk_rules, &oldtsp->smk_rules, GFP_KERNEL);
- if (rc != 0)
- return rc;
-
- new->security = tsp;
- commit_creds(new);
- return size;
-}
-
-/**
- * smack_unix_stream_connect - Smack access on UDS
- * @sock: one sock
- * @other: the other sock
- * @newsk: unused
- *
- * Return 0 if a subject with the smack of sock could access
- * an object with the smack of other, otherwise an error code
- */
-static int smack_unix_stream_connect(struct sock *sock,
- struct sock *other, struct sock *newsk)
-{
- struct socket_smack *ssp = sock->sk_security;
- struct socket_smack *osp = other->sk_security;
- struct socket_smack *nsp = newsk->sk_security;
- struct smk_audit_info ad;
- int rc = 0;
-
-#ifdef CONFIG_AUDIT
- struct lsm_network_audit net;
-
- smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
- smk_ad_setfield_u_net_sk(&ad, other);
-#endif
-
- if (!capable(CAP_MAC_OVERRIDE))
- rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
-
- /*
- * Cross reference the peer labels for SO_PEERSEC.
- */
- if (rc == 0) {
- nsp->smk_packet = ssp->smk_out;
- ssp->smk_packet = osp->smk_out;
- }
-
- return rc;
-}
-
-/**
- * smack_unix_may_send - Smack access on UDS
- * @sock: one socket
- * @other: the other socket
- *
- * Return 0 if a subject with the smack of sock could access
- * an object with the smack of other, otherwise an error code
- */
-static int smack_unix_may_send(struct socket *sock, struct socket *other)
-{
- struct socket_smack *ssp = sock->sk->sk_security;
- struct socket_smack *osp = other->sk->sk_security;
- struct smk_audit_info ad;
- int rc = 0;
-
-#ifdef CONFIG_AUDIT
- struct lsm_network_audit net;
-
- smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
- smk_ad_setfield_u_net_sk(&ad, other->sk);
-#endif
-
- if (!capable(CAP_MAC_OVERRIDE))
- rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
-
- return rc;
-}
-
-/**
- * smack_socket_sendmsg - Smack check based on destination host
- * @sock: the socket
- * @msg: the message
- * @size: the size of the message
- *
- * Return 0 if the current subject can write to the destination
- * host. This is only a question if the destination is a single
- * label host.
- */
-static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
- int size)
-{
- struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
-
- /*
- * Perfectly reasonable for this to be NULL
- */
- if (sip == NULL || sip->sin_family != AF_INET)
- return 0;
-
- return smack_netlabel_send(sock->sk, sip);
-}
-
-/**
- * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat pair to smack
- * @sap: netlabel secattr
- * @ssp: socket security information
- *
- * Returns a pointer to a Smack label found on the label list.
- */
-static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
- struct socket_smack *ssp)
-{
- struct smack_known *skp;
- char smack[SMK_LABELLEN];
- char *sp;
- int pcat;
-
- if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
- /*
- * Looks like a CIPSO packet.
- * If there are flags but no level netlabel isn't
- * behaving the way we expect it to.
- *
- * Get the categories, if any
- * Without guidance regarding the smack value
- * for the packet fall back on the network
- * ambient value.
- */
- memset(smack, '\0', SMK_LABELLEN);
- if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0)
- for (pcat = -1;;) {
- pcat = netlbl_secattr_catmap_walk(
- sap->attr.mls.cat, pcat + 1);
- if (pcat < 0)
- break;
- smack_catset_bit(pcat, smack);
- }
- /*
- * If it is CIPSO using smack direct mapping
- * we are already done. WeeHee.
- */
- if (sap->attr.mls.lvl == smack_cipso_direct) {
- /*
- * The label sent is usually on the label list.
- *
- * If it is not we may still want to allow the
- * delivery.
- *
- * If the recipient is accepting all packets
- * because it is using the star ("*") label
- * for SMACK64IPIN provide the web ("@") label
- * so that a directed response will succeed.
- * This is not very correct from a MAC point
- * of view, but gets around the problem that
- * locking prevents adding the newly discovered
- * label to the list.
- * The case where the recipient is not using
- * the star label should obviously fail.
- * The easy way to do this is to provide the
- * star label as the subject label.
- */
- skp = smk_find_entry(smack);
- if (skp != NULL)
- return skp->smk_known;
- if (ssp != NULL &&
- ssp->smk_in == smack_known_star.smk_known)
- return smack_known_web.smk_known;
- return smack_known_star.smk_known;
- }
- /*
- * Look it up in the supplied table if it is not
- * a direct mapping.
- */
- sp = smack_from_cipso(sap->attr.mls.lvl, smack);
- if (sp != NULL)
- return sp;
- if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known)
- return smack_known_web.smk_known;
- return smack_known_star.smk_known;
- }
- if ((sap->flags & NETLBL_SECATTR_SECID) != 0) {
- /*
- * Looks like a fallback, which gives us a secid.
- */
- sp = smack_from_secid(sap->attr.secid);
- /*
- * This has got to be a bug because it is
- * impossible to specify a fallback without
- * specifying the label, which will ensure
- * it has a secid, and the only way to get a
- * secid is from a fallback.
- */
- BUG_ON(sp == NULL);
- return sp;
- }
- /*
- * Without guidance regarding the smack value
- * for the packet fall back on the network
- * ambient value.
- */
- return smack_net_ambient;
-}
-
-/**
- * smack_socket_sock_rcv_skb - Smack packet delivery access check
- * @sk: socket
- * @skb: packet
- *
- * Returns 0 if the packet should be delivered, an error code otherwise
- */
-static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
-{
- struct netlbl_lsm_secattr secattr;
- struct socket_smack *ssp = sk->sk_security;
- char *csp;
- int rc;
- struct smk_audit_info ad;
-#ifdef CONFIG_AUDIT
- struct lsm_network_audit net;
-#endif
- if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
- return 0;
-
- /*
- * Translate what netlabel gave us.
- */
- netlbl_secattr_init(&secattr);
-
- rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr);
- if (rc == 0)
- csp = smack_from_secattr(&secattr, ssp);
- else
- csp = smack_net_ambient;
-
- netlbl_secattr_destroy(&secattr);
-
-#ifdef CONFIG_AUDIT
- smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
- ad.a.u.net->family = sk->sk_family;
- ad.a.u.net->netif = skb->skb_iif;
- ipv4_skb_to_auditdata(skb, &ad.a, NULL);
-#endif
- /*
- * Receiving a packet requires that the other end
- * be able to write here. Read access is not required.
- * This is the simplist possible security model
- * for networking.
- */
- rc = smk_access(csp, ssp->smk_in, MAY_WRITE, &ad);
- if (rc != 0)
- netlbl_skbuff_err(skb, rc, 0);
- return rc;
-}
-
-/**
- * smack_socket_getpeersec_stream - pull in packet label
- * @sock: the socket
- * @optval: user's destination
- * @optlen: size thereof
- * @len: max thereof
- *
- * returns zero on success, an error code otherwise
- */
-static int smack_socket_getpeersec_stream(struct socket *sock,
- char __user *optval,
- int __user *optlen, unsigned len)
-{
- struct socket_smack *ssp;
- char *rcp = "";
- int slen = 1;
- int rc = 0;
-
- ssp = sock->sk->sk_security;
- if (ssp->smk_packet != NULL) {
- rcp = ssp->smk_packet;
- slen = strlen(rcp) + 1;
- }
-
- if (slen > len)
- rc = -ERANGE;
- else if (copy_to_user(optval, rcp, slen) != 0)
- rc = -EFAULT;
-
- if (put_user(slen, optlen) != 0)
- rc = -EFAULT;
-
- return rc;
-}
-
-
-/**
- * smack_socket_getpeersec_dgram - pull in packet label
- * @sock: the peer socket
- * @skb: packet data
- * @secid: pointer to where to put the secid of the packet
- *
- * Sets the netlabel socket state on sk from parent
- */
-static int smack_socket_getpeersec_dgram(struct socket *sock,
- struct sk_buff *skb, u32 *secid)
-
-{
- struct netlbl_lsm_secattr secattr;
- struct socket_smack *ssp = NULL;
- char *sp;
- int family = PF_UNSPEC;
- u32 s = 0; /* 0 is the invalid secid */
- int rc;
-
- if (skb != NULL) {
- if (skb->protocol == htons(ETH_P_IP))
- family = PF_INET;
- else if (skb->protocol == htons(ETH_P_IPV6))
- family = PF_INET6;
- }
- if (family == PF_UNSPEC && sock != NULL)
- family = sock->sk->sk_family;
-
- if (family == PF_UNIX) {
- ssp = sock->sk->sk_security;
- s = smack_to_secid(ssp->smk_out);
- } else if (family == PF_INET || family == PF_INET6) {
- /*
- * Translate what netlabel gave us.
- */
- if (sock != NULL && sock->sk != NULL)
- ssp = sock->sk->sk_security;
- netlbl_secattr_init(&secattr);
- rc = netlbl_skbuff_getattr(skb, family, &secattr);
- if (rc == 0) {
- sp = smack_from_secattr(&secattr, ssp);
- s = smack_to_secid(sp);
- }
- netlbl_secattr_destroy(&secattr);
- }
- *secid = s;
- if (s == 0)
- return -EINVAL;
- return 0;
-}
-
-/**
- * smack_sock_graft - Initialize a newly created socket with an existing sock
- * @sk: child sock
- * @parent: parent socket
- *
- * Set the smk_{in,out} state of an existing sock based on the process that
- * is creating the new socket.
- */
-static void smack_sock_graft(struct sock *sk, struct socket *parent)
-{
- struct socket_smack *ssp;
-
- if (sk == NULL ||
- (sk->sk_family != PF_INET && sk->sk_family != PF_INET6))
- return;
-
- ssp = sk->sk_security;
- ssp->smk_in = ssp->smk_out = smk_of_current();
- /* cssp->smk_packet is already set in smack_inet_csk_clone() */
-}
-
-/**
- * smack_inet_conn_request - Smack access check on connect
- * @sk: socket involved
- * @skb: packet
- * @req: unused
- *
- * Returns 0 if a task with the packet label could write to
- * the socket, otherwise an error code
- */
-static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
- struct request_sock *req)
-{
- u16 family = sk->sk_family;
- struct socket_smack *ssp = sk->sk_security;
- struct netlbl_lsm_secattr secattr;
- struct sockaddr_in addr;
- struct iphdr *hdr;
- char *sp;
- int rc;
- struct smk_audit_info ad;
-#ifdef CONFIG_AUDIT
- struct lsm_network_audit net;
-#endif
-
- /* handle mapped IPv4 packets arriving via IPv6 sockets */
- if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
- family = PF_INET;
-
- netlbl_secattr_init(&secattr);
- rc = netlbl_skbuff_getattr(skb, family, &secattr);
- if (rc == 0)
- sp = smack_from_secattr(&secattr, ssp);
- else
- sp = smack_known_huh.smk_known;
- netlbl_secattr_destroy(&secattr);
-
-#ifdef CONFIG_AUDIT
- smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
- ad.a.u.net->family = family;
- ad.a.u.net->netif = skb->skb_iif;
- ipv4_skb_to_auditdata(skb, &ad.a, NULL);
-#endif
- /*
- * Receiving a packet requires that the other end be able to write
- * here. Read access is not required.
- */
- rc = smk_access(sp, ssp->smk_in, MAY_WRITE, &ad);
- if (rc != 0)
- return rc;
-
- /*
- * Save the peer's label in the request_sock so we can later setup
- * smk_packet in the child socket so that SO_PEERCRED can report it.
- */
- req->peer_secid = smack_to_secid(sp);
-
- /*
- * We need to decide if we want to label the incoming connection here
- * if we do we only need to label the request_sock and the stack will
- * propagate the wire-label to the sock when it is created.
- */
- hdr = ip_hdr(skb);
- addr.sin_addr.s_addr = hdr->saddr;
- rcu_read_lock();
- if (smack_host_label(&addr) == NULL) {
- rcu_read_unlock();
- netlbl_secattr_init(&secattr);
- smack_to_secattr(sp, &secattr);
- rc = netlbl_req_setattr(req, &secattr);
- netlbl_secattr_destroy(&secattr);
- } else {
- rcu_read_unlock();
- netlbl_req_delattr(req);
- }
-
- return rc;
-}
-
-/**
- * smack_inet_csk_clone - Copy the connection information to the new socket
- * @sk: the new socket
- * @req: the connection's request_sock
- *
- * Transfer the connection's peer label to the newly created socket.
- */
-static void smack_inet_csk_clone(struct sock *sk,
- const struct request_sock *req)
-{
- struct socket_smack *ssp = sk->sk_security;
-
- if (req->peer_secid != 0)
- ssp->smk_packet = smack_from_secid(req->peer_secid);
- else
- ssp->smk_packet = NULL;
-}
-
-/*
- * Key management security hooks
- *
- * Casey has not tested key support very heavily.
- * The permission check is most likely too restrictive.
- * If you care about keys please have a look.
- */
-#ifdef CONFIG_KEYS
-
-/**
- * smack_key_alloc - Set the key security blob
- * @key: object
- * @cred: the credentials to use
- * @flags: unused
- *
- * No allocation required
- *
- * Returns 0
- */
-static int smack_key_alloc(struct key *key, const struct cred *cred,
- unsigned long flags)
-{
- key->security = smk_of_task(cred->security);
- return 0;
-}
-
-/**
- * smack_key_free - Clear the key security blob
- * @key: the object
- *
- * Clear the blob pointer
- */
-static void smack_key_free(struct key *key)
-{
- key->security = NULL;
-}
-
-/*
- * smack_key_permission - Smack access on a key
- * @key_ref: gets to the object
- * @cred: the credentials to use
- * @perm: unused
- *
- * Return 0 if the task has read and write to the object,
- * an error code otherwise
- */
-static int smack_key_permission(key_ref_t key_ref,
- const struct cred *cred, key_perm_t perm)
-{
- struct key *keyp;
- struct smk_audit_info ad;
- char *tsp = smk_of_task(cred->security);
-
- keyp = key_ref_to_ptr(key_ref);
- if (keyp == NULL)
- return -EINVAL;
- /*
- * If the key hasn't been initialized give it access so that
- * it may do so.
- */
- if (keyp->security == NULL)
- return 0;
- /*
- * This should not occur
- */
- if (tsp == NULL)
- return -EACCES;
-#ifdef CONFIG_AUDIT
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY);
- ad.a.u.key_struct.key = keyp->serial;
- ad.a.u.key_struct.key_desc = keyp->description;
-#endif
- return smk_access(tsp, keyp->security,
- MAY_READWRITE, &ad);
-}
-#endif /* CONFIG_KEYS */
-
-/*
- * Smack Audit hooks
- *
- * Audit requires a unique representation of each Smack specific
- * rule. This unique representation is used to distinguish the
- * object to be audited from remaining kernel objects and also
- * works as a glue between the audit hooks.
- *
- * Since repository entries are added but never deleted, we'll use
- * the smack_known label address related to the given audit rule as
- * the needed unique representation. This also better fits the smack
- * model where nearly everything is a label.
- */
-#ifdef CONFIG_AUDIT
-
-/**
- * smack_audit_rule_init - Initialize a smack audit rule
- * @field: audit rule fields given from user-space (audit.h)
- * @op: required testing operator (=, !=, >, <, ...)
- * @rulestr: smack label to be audited
- * @vrule: pointer to save our own audit rule representation
- *
- * Prepare to audit cases where (@field @op @rulestr) is true.
- * The label to be audited is created if necessay.
- */
-static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
-{
- char **rule = (char **)vrule;
- *rule = NULL;
-
- if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER)
- return -EINVAL;
-
- if (op != Audit_equal && op != Audit_not_equal)
- return -EINVAL;
-
- *rule = smk_import(rulestr, 0);
-
- return 0;
-}
-
-/**
- * smack_audit_rule_known - Distinguish Smack audit rules
- * @krule: rule of interest, in Audit kernel representation format
- *
- * This is used to filter Smack rules from remaining Audit ones.
- * If it's proved that this rule belongs to us, the
- * audit_rule_match hook will be called to do the final judgement.
- */
-static int smack_audit_rule_known(struct audit_krule *krule)
-{
- struct audit_field *f;
- int i;
-
- for (i = 0; i < krule->field_count; i++) {
- f = &krule->fields[i];
-
- if (f->type == AUDIT_SUBJ_USER || f->type == AUDIT_OBJ_USER)
- return 1;
- }
-
- return 0;
-}
-
-/**
- * smack_audit_rule_match - Audit given object ?
- * @secid: security id for identifying the object to test
- * @field: audit rule flags given from user-space
- * @op: required testing operator
- * @vrule: smack internal rule presentation
- * @actx: audit context associated with the check
- *
- * The core Audit hook. It's used to take the decision of
- * whether to audit or not to audit a given object.
- */
-static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule,
- struct audit_context *actx)
-{
- char *smack;
- char *rule = vrule;
-
- if (!rule) {
- audit_log(actx, GFP_KERNEL, AUDIT_SELINUX_ERR,
- "Smack: missing rule\n");
- return -ENOENT;
- }
-
- if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER)
- return 0;
-
- smack = smack_from_secid(secid);
-
- /*
- * No need to do string comparisons. If a match occurs,
- * both pointers will point to the same smack_known
- * label.
- */
- if (op == Audit_equal)
- return (rule == smack);
- if (op == Audit_not_equal)
- return (rule != smack);
-
- return 0;
-}
-
-/**
- * smack_audit_rule_free - free smack rule representation
- * @vrule: rule to be freed.
- *
- * No memory was allocated.
- */
-static void smack_audit_rule_free(void *vrule)
-{
- /* No-op */
-}
-
-#endif /* CONFIG_AUDIT */
-
-/**
- * smack_secid_to_secctx - return the smack label for a secid
- * @secid: incoming integer
- * @secdata: destination
- * @seclen: how long it is
- *
- * Exists for networking code.
- */
-static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
-{
- char *sp = smack_from_secid(secid);
-
- if (secdata)
- *secdata = sp;
- *seclen = strlen(sp);
- return 0;
-}
-
-/**
- * smack_secctx_to_secid - return the secid for a smack label
- * @secdata: smack label
- * @seclen: how long result is
- * @secid: outgoing integer
- *
- * Exists for audit and networking code.
- */
-static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
-{
- *secid = smack_to_secid(secdata);
- return 0;
-}
-
-/**
- * smack_release_secctx - don't do anything.
- * @secdata: unused
- * @seclen: unused
- *
- * Exists to make sure nothing gets done, and properly
- */
-static void smack_release_secctx(char *secdata, u32 seclen)
-{
-}
-
-static int smack_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
-{
- return smack_inode_setsecurity(inode, XATTR_SMACK_SUFFIX, ctx, ctxlen, 0);
-}
-
-static int smack_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
-{
- return __vfs_setxattr_noperm(dentry, XATTR_NAME_SMACK, ctx, ctxlen, 0);
-}
-
-static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
-{
- int len = 0;
- len = smack_inode_getsecurity(inode, XATTR_SMACK_SUFFIX, ctx, true);
-
- if (len < 0)
- return len;
- *ctxlen = len;
- return 0;
-}
-
-struct security_operations smack_ops = {
- .name = "smack",
-
- .ptrace_access_check = smack_ptrace_access_check,
- .ptrace_traceme = smack_ptrace_traceme,
- .syslog = smack_syslog,
-
- .sb_alloc_security = smack_sb_alloc_security,
- .sb_free_security = smack_sb_free_security,
- .sb_copy_data = smack_sb_copy_data,
- .sb_kern_mount = smack_sb_kern_mount,
- .sb_statfs = smack_sb_statfs,
- .sb_mount = smack_sb_mount,
- .sb_umount = smack_sb_umount,
-
- .bprm_set_creds = smack_bprm_set_creds,
- .bprm_committing_creds = smack_bprm_committing_creds,
- .bprm_secureexec = smack_bprm_secureexec,
-
- .inode_alloc_security = smack_inode_alloc_security,
- .inode_free_security = smack_inode_free_security,
- .inode_init_security = smack_inode_init_security,
- .inode_link = smack_inode_link,
- .inode_unlink = smack_inode_unlink,
- .inode_rmdir = smack_inode_rmdir,
- .inode_rename = smack_inode_rename,
- .inode_permission = smack_inode_permission,
- .inode_setattr = smack_inode_setattr,
- .inode_getattr = smack_inode_getattr,
- .inode_setxattr = smack_inode_setxattr,
- .inode_post_setxattr = smack_inode_post_setxattr,
- .inode_getxattr = smack_inode_getxattr,
- .inode_removexattr = smack_inode_removexattr,
- .inode_getsecurity = smack_inode_getsecurity,
- .inode_setsecurity = smack_inode_setsecurity,
- .inode_listsecurity = smack_inode_listsecurity,
- .inode_getsecid = smack_inode_getsecid,
-
- .file_permission = smack_file_permission,
- .file_alloc_security = smack_file_alloc_security,
- .file_free_security = smack_file_free_security,
- .file_ioctl = smack_file_ioctl,
- .file_lock = smack_file_lock,
- .file_fcntl = smack_file_fcntl,
- .file_mmap = smack_file_mmap,
- .file_set_fowner = smack_file_set_fowner,
- .file_send_sigiotask = smack_file_send_sigiotask,
- .file_receive = smack_file_receive,
-
- .dentry_open = smack_dentry_open,
-
- .cred_alloc_blank = smack_cred_alloc_blank,
- .cred_free = smack_cred_free,
- .cred_prepare = smack_cred_prepare,
- .cred_transfer = smack_cred_transfer,
- .kernel_act_as = smack_kernel_act_as,
- .kernel_create_files_as = smack_kernel_create_files_as,
- .task_setpgid = smack_task_setpgid,
- .task_getpgid = smack_task_getpgid,
- .task_getsid = smack_task_getsid,
- .task_getsecid = smack_task_getsecid,
- .task_setnice = smack_task_setnice,
- .task_setioprio = smack_task_setioprio,
- .task_getioprio = smack_task_getioprio,
- .task_setscheduler = smack_task_setscheduler,
- .task_getscheduler = smack_task_getscheduler,
- .task_movememory = smack_task_movememory,
- .task_kill = smack_task_kill,
- .task_wait = smack_task_wait,
- .task_to_inode = smack_task_to_inode,
-
- .ipc_permission = smack_ipc_permission,
- .ipc_getsecid = smack_ipc_getsecid,
-
- .msg_msg_alloc_security = smack_msg_msg_alloc_security,
- .msg_msg_free_security = smack_msg_msg_free_security,
-
- .msg_queue_alloc_security = smack_msg_queue_alloc_security,
- .msg_queue_free_security = smack_msg_queue_free_security,
- .msg_queue_associate = smack_msg_queue_associate,
- .msg_queue_msgctl = smack_msg_queue_msgctl,
- .msg_queue_msgsnd = smack_msg_queue_msgsnd,
- .msg_queue_msgrcv = smack_msg_queue_msgrcv,
-
- .shm_alloc_security = smack_shm_alloc_security,
- .shm_free_security = smack_shm_free_security,
- .shm_associate = smack_shm_associate,
- .shm_shmctl = smack_shm_shmctl,
- .shm_shmat = smack_shm_shmat,
-
- .sem_alloc_security = smack_sem_alloc_security,
- .sem_free_security = smack_sem_free_security,
- .sem_associate = smack_sem_associate,
- .sem_semctl = smack_sem_semctl,
- .sem_semop = smack_sem_semop,
-
- .d_instantiate = smack_d_instantiate,
-
- .getprocattr = smack_getprocattr,
- .setprocattr = smack_setprocattr,
-
- .unix_stream_connect = smack_unix_stream_connect,
- .unix_may_send = smack_unix_may_send,
-
- .socket_post_create = smack_socket_post_create,
- .socket_connect = smack_socket_connect,
- .socket_sendmsg = smack_socket_sendmsg,
- .socket_sock_rcv_skb = smack_socket_sock_rcv_skb,
- .socket_getpeersec_stream = smack_socket_getpeersec_stream,
- .socket_getpeersec_dgram = smack_socket_getpeersec_dgram,
- .sk_alloc_security = smack_sk_alloc_security,
- .sk_free_security = smack_sk_free_security,
- .sock_graft = smack_sock_graft,
- .inet_conn_request = smack_inet_conn_request,
- .inet_csk_clone = smack_inet_csk_clone,
-
- /* key management security hooks */
-#ifdef CONFIG_KEYS
- .key_alloc = smack_key_alloc,
- .key_free = smack_key_free,
- .key_permission = smack_key_permission,
-#endif /* CONFIG_KEYS */
-
- /* Audit hooks */
-#ifdef CONFIG_AUDIT
- .audit_rule_init = smack_audit_rule_init,
- .audit_rule_known = smack_audit_rule_known,
- .audit_rule_match = smack_audit_rule_match,
- .audit_rule_free = smack_audit_rule_free,
-#endif /* CONFIG_AUDIT */
-
- .secid_to_secctx = smack_secid_to_secctx,
- .secctx_to_secid = smack_secctx_to_secid,
- .release_secctx = smack_release_secctx,
- .inode_notifysecctx = smack_inode_notifysecctx,
- .inode_setsecctx = smack_inode_setsecctx,
- .inode_getsecctx = smack_inode_getsecctx,
-};
-
-
-static __init void init_smack_known_list(void)
-{
- /*
- * Initialize CIPSO locks
- */
- spin_lock_init(&smack_known_huh.smk_cipsolock);
- spin_lock_init(&smack_known_hat.smk_cipsolock);
- spin_lock_init(&smack_known_star.smk_cipsolock);
- spin_lock_init(&smack_known_floor.smk_cipsolock);
- spin_lock_init(&smack_known_invalid.smk_cipsolock);
- spin_lock_init(&smack_known_web.smk_cipsolock);
- /*
- * Initialize rule list locks
- */
- mutex_init(&smack_known_huh.smk_rules_lock);
- mutex_init(&smack_known_hat.smk_rules_lock);
- mutex_init(&smack_known_floor.smk_rules_lock);
- mutex_init(&smack_known_star.smk_rules_lock);
- mutex_init(&smack_known_invalid.smk_rules_lock);
- mutex_init(&smack_known_web.smk_rules_lock);
- /*
- * Initialize rule lists
- */
- INIT_LIST_HEAD(&smack_known_huh.smk_rules);
- INIT_LIST_HEAD(&smack_known_hat.smk_rules);
- INIT_LIST_HEAD(&smack_known_star.smk_rules);
- INIT_LIST_HEAD(&smack_known_floor.smk_rules);
- INIT_LIST_HEAD(&smack_known_invalid.smk_rules);
- INIT_LIST_HEAD(&smack_known_web.smk_rules);
- /*
- * Create the known labels list
- */
- list_add(&smack_known_huh.list, &smack_known_list);
- list_add(&smack_known_hat.list, &smack_known_list);
- list_add(&smack_known_star.list, &smack_known_list);
- list_add(&smack_known_floor.list, &smack_known_list);
- list_add(&smack_known_invalid.list, &smack_known_list);
- list_add(&smack_known_web.list, &smack_known_list);
-}
-
-/**
- * smack_init - initialize the smack system
- *
- * Returns 0
- */
-static __init int smack_init(void)
-{
- struct cred *cred;
- struct task_smack *tsp;
-
- if (!security_module_enable(&smack_ops))
- return 0;
-
- tsp = new_task_smack(smack_known_floor.smk_known,
- smack_known_floor.smk_known, GFP_KERNEL);
- if (tsp == NULL)
- return -ENOMEM;
-
- printk(KERN_INFO "Smack: Initializing.\n");
-
- /*
- * Set the security state for the initial task.
- */
- cred = (struct cred *) current->cred;
- cred->security = tsp;
-
- /* initialize the smack_known_list */
- init_smack_known_list();
-
- /*
- * Register with LSM
- */
- if (register_security(&smack_ops))
- panic("smack: Unable to register with kernel.\n");
-
- return 0;
-}
-
-/*
- * Smack requires early initialization in order to label
- * all processes and objects when they are created.
- */
-security_initcall(smack_init);
diff --git a/ANDROID_3.4.5/security/smack/smackfs.c b/ANDROID_3.4.5/security/smack/smackfs.c
deleted file mode 100644
index 038811cb..00000000
--- a/ANDROID_3.4.5/security/smack/smackfs.c
+++ /dev/null
@@ -1,1620 +0,0 @@
-/*
- * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
- *
- * Authors:
- * Casey Schaufler <casey@schaufler-ca.com>
- * Ahmed S. Darwish <darwish.07@gmail.com>
- *
- * Special thanks to the authors of selinuxfs.
- *
- * Karl MacMillan <kmacmillan@tresys.com>
- * James Morris <jmorris@redhat.com>
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/vmalloc.h>
-#include <linux/security.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <net/net_namespace.h>
-#include <net/netlabel.h>
-#include <net/cipso_ipv4.h>
-#include <linux/seq_file.h>
-#include <linux/ctype.h>
-#include <linux/audit.h>
-#include "smack.h"
-
-/*
- * smackfs pseudo filesystem.
- */
-
-enum smk_inos {
- SMK_ROOT_INO = 2,
- SMK_LOAD = 3, /* load policy */
- SMK_CIPSO = 4, /* load label -> CIPSO mapping */
- SMK_DOI = 5, /* CIPSO DOI */
- SMK_DIRECT = 6, /* CIPSO level indicating direct label */
- SMK_AMBIENT = 7, /* internet ambient label */
- SMK_NETLBLADDR = 8, /* single label hosts */
- SMK_ONLYCAP = 9, /* the only "capable" label */
- SMK_LOGGING = 10, /* logging */
- SMK_LOAD_SELF = 11, /* task specific rules */
- SMK_ACCESSES = 12, /* access policy */
-};
-
-/*
- * List locks
- */
-static DEFINE_MUTEX(smack_list_lock);
-static DEFINE_MUTEX(smack_cipso_lock);
-static DEFINE_MUTEX(smack_ambient_lock);
-static DEFINE_MUTEX(smk_netlbladdr_lock);
-
-/*
- * This is the "ambient" label for network traffic.
- * If it isn't somehow marked, use this.
- * It can be reset via smackfs/ambient
- */
-char *smack_net_ambient = smack_known_floor.smk_known;
-
-/*
- * This is the level in a CIPSO header that indicates a
- * smack label is contained directly in the category set.
- * It can be reset via smackfs/direct
- */
-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.
- */
-
-LIST_HEAD(smk_netlbladdr_list);
-
-/*
- * Rule lists are maintained for each label.
- * This master list is just for reading /smack/load.
- */
-struct smack_master_list {
- struct list_head list;
- struct smack_rule *smk_rule;
-};
-
-LIST_HEAD(smack_rule_list);
-
-static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
-
-const char *smack_cipso_option = SMACK_CIPSO_OPTION;
-
-/*
- * Values for parsing cipso rules
- * SMK_DIGITLEN: Length of a digit field in a rule.
- * SMK_CIPSOMIN: Minimum possible cipso rule length.
- * SMK_CIPSOMAX: Maximum possible cipso rule length.
- */
-#define SMK_DIGITLEN 4
-#define SMK_CIPSOMIN (SMK_LABELLEN + 2 * SMK_DIGITLEN)
-#define SMK_CIPSOMAX (SMK_CIPSOMIN + SMACK_CIPSO_MAXCATNUM * SMK_DIGITLEN)
-
-/*
- * Values for parsing MAC rules
- * SMK_ACCESS: Maximum possible combination of access permissions
- * SMK_ACCESSLEN: Maximum length for a rule access field
- * SMK_LOADLEN: Smack rule length
- */
-#define SMK_OACCESS "rwxa"
-#define SMK_ACCESS "rwxat"
-#define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1)
-#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
-#define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN)
-#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
-
-/**
- * smk_netlabel_audit_set - fill a netlbl_audit struct
- * @nap: structure to fill
- */
-static void smk_netlabel_audit_set(struct netlbl_audit *nap)
-{
- nap->loginuid = audit_get_loginuid(current);
- nap->sessionid = audit_get_sessionid(current);
- nap->secid = smack_to_secid(smk_of_current());
-}
-
-/*
- * Values for parsing single label host rules
- * "1.2.3.4 X"
- * "192.168.138.129/32 abcdefghijklmnopqrstuvw"
- */
-#define SMK_NETLBLADDRMIN 9
-#define SMK_NETLBLADDRMAX 42
-
-/**
- * smk_set_access - add a rule to the rule list
- * @srp: the new rule to add
- * @rule_list: the list of rules
- * @rule_lock: the rule list lock
- *
- * Looks through the current subject/object/access list for
- * the subject/object pair and replaces the access that was
- * there. If the pair isn't found add it with the specified
- * access.
- *
- * Returns 1 if a rule was found to exist already, 0 if it is new
- * Returns 0 if nothing goes wrong or -ENOMEM if it fails
- * during the allocation of the new pair to add.
- */
-static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
- struct mutex *rule_lock)
-{
- struct smack_rule *sp;
- int found = 0;
-
- mutex_lock(rule_lock);
-
- /*
- * Because the object label is less likely to match
- * than the subject label check it first
- */
- list_for_each_entry_rcu(sp, rule_list, list) {
- if (sp->smk_object == srp->smk_object &&
- sp->smk_subject == srp->smk_subject) {
- found = 1;
- sp->smk_access = srp->smk_access;
- break;
- }
- }
- if (found == 0)
- list_add_rcu(&srp->list, rule_list);
-
- mutex_unlock(rule_lock);
-
- return found;
-}
-
-/**
- * smk_parse_rule - parse Smack rule from load string
- * @data: string to be parsed whose size is SMK_LOADLEN
- * @rule: Smack rule
- * @import: if non-zero, import labels
- */
-static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
-{
- char smack[SMK_LABELLEN];
- struct smack_known *skp;
-
- if (import) {
- rule->smk_subject = smk_import(data, 0);
- if (rule->smk_subject == NULL)
- return -1;
-
- rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
- if (rule->smk_object == NULL)
- return -1;
- } else {
- smk_parse_smack(data, 0, smack);
- skp = smk_find_entry(smack);
- if (skp == NULL)
- return -1;
- rule->smk_subject = skp->smk_known;
-
- smk_parse_smack(data + SMK_LABELLEN, 0, smack);
- skp = smk_find_entry(smack);
- if (skp == NULL)
- return -1;
- rule->smk_object = skp->smk_known;
- }
-
- rule->smk_access = 0;
-
- switch (data[SMK_LABELLEN + SMK_LABELLEN]) {
- case '-':
- break;
- case 'r':
- case 'R':
- rule->smk_access |= MAY_READ;
- break;
- default:
- return -1;
- }
-
- switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) {
- case '-':
- break;
- case 'w':
- case 'W':
- rule->smk_access |= MAY_WRITE;
- break;
- default:
- return -1;
- }
-
- switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) {
- case '-':
- break;
- case 'x':
- case 'X':
- rule->smk_access |= MAY_EXEC;
- break;
- default:
- return -1;
- }
-
- switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) {
- case '-':
- break;
- case 'a':
- case 'A':
- rule->smk_access |= MAY_APPEND;
- break;
- default:
- return -1;
- }
-
- switch (data[SMK_LABELLEN + SMK_LABELLEN + 4]) {
- case '-':
- break;
- case 't':
- case 'T':
- rule->smk_access |= MAY_TRANSMUTE;
- break;
- default:
- return -1;
- }
-
- return 0;
-}
-
-/**
- * smk_write_load_list - write() for any /smack/load
- * @file: file pointer, not actually used
- * @buf: where to get the data from
- * @count: bytes sent
- * @ppos: where to start - must be 0
- * @rule_list: the list of rules to write to
- * @rule_lock: lock for the rule list
- *
- * Get one smack access rule from above.
- * The format is exactly:
- * char subject[SMK_LABELLEN]
- * char object[SMK_LABELLEN]
- * char access[SMK_ACCESSLEN]
- *
- * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes.
- */
-static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos,
- struct list_head *rule_list,
- struct mutex *rule_lock)
-{
- struct smack_master_list *smlp;
- struct smack_known *skp;
- struct smack_rule *rule;
- char *data;
- int rc = -EINVAL;
- int load = 0;
-
- /*
- * No partial writes.
- * Enough data must be present.
- */
- if (*ppos != 0)
- return -EINVAL;
- /*
- * Minor hack for backward compatibility
- */
- if (count < (SMK_OLOADLEN) || count > SMK_LOADLEN)
- return -EINVAL;
-
- data = kzalloc(SMK_LOADLEN, GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(data, buf, count) != 0) {
- rc = -EFAULT;
- goto out;
- }
-
- /*
- * More on the minor hack for backward compatibility
- */
- if (count == (SMK_OLOADLEN))
- data[SMK_OLOADLEN] = '-';
-
- rule = kzalloc(sizeof(*rule), GFP_KERNEL);
- if (rule == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- if (smk_parse_rule(data, rule, 1))
- goto out_free_rule;
-
- if (rule_list == NULL) {
- load = 1;
- skp = smk_find_entry(rule->smk_subject);
- rule_list = &skp->smk_rules;
- rule_lock = &skp->smk_rules_lock;
- }
-
- rc = count;
- /*
- * If this is "load" as opposed to "load-self" and a new rule
- * it needs to get added for reporting.
- * smk_set_access returns true if there was already a rule
- * for the subject/object pair, and false if it was new.
- */
- if (load && !smk_set_access(rule, rule_list, rule_lock)) {
- smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
- if (smlp != NULL) {
- smlp->smk_rule = rule;
- list_add_rcu(&smlp->list, &smack_rule_list);
- } else
- rc = -ENOMEM;
- goto out;
- }
-
-out_free_rule:
- kfree(rule);
-out:
- kfree(data);
- return rc;
-}
-
-/*
- * Core logic for smackfs seq list operations.
- */
-
-static void *smk_seq_start(struct seq_file *s, loff_t *pos,
- struct list_head *head)
-{
- struct list_head *list;
-
- /*
- * This is 0 the first time through.
- */
- if (s->index == 0)
- s->private = head;
-
- if (s->private == NULL)
- return NULL;
-
- list = s->private;
- if (list_empty(list))
- return NULL;
-
- if (s->index == 0)
- return list->next;
- return list;
-}
-
-static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
- struct list_head *head)
-{
- struct list_head *list = v;
-
- if (list_is_last(list, head)) {
- s->private = NULL;
- return NULL;
- }
- s->private = list->next;
- return list->next;
-}
-
-static void smk_seq_stop(struct seq_file *s, void *v)
-{
- /* No-op */
-}
-
-/*
- * Seq_file read operations for /smack/load
- */
-
-static void *load_seq_start(struct seq_file *s, loff_t *pos)
-{
- return smk_seq_start(s, pos, &smack_rule_list);
-}
-
-static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
- return smk_seq_next(s, v, pos, &smack_rule_list);
-}
-
-static int load_seq_show(struct seq_file *s, void *v)
-{
- struct list_head *list = v;
- struct smack_master_list *smlp =
- list_entry(list, struct smack_master_list, list);
- struct smack_rule *srp = smlp->smk_rule;
-
- seq_printf(s, "%s %s", (char *)srp->smk_subject,
- (char *)srp->smk_object);
-
- seq_putc(s, ' ');
-
- if (srp->smk_access & MAY_READ)
- seq_putc(s, 'r');
- if (srp->smk_access & MAY_WRITE)
- seq_putc(s, 'w');
- if (srp->smk_access & MAY_EXEC)
- seq_putc(s, 'x');
- if (srp->smk_access & MAY_APPEND)
- seq_putc(s, 'a');
- if (srp->smk_access & MAY_TRANSMUTE)
- seq_putc(s, 't');
- if (srp->smk_access == 0)
- seq_putc(s, '-');
-
- seq_putc(s, '\n');
-
- return 0;
-}
-
-static const struct seq_operations load_seq_ops = {
- .start = load_seq_start,
- .next = load_seq_next,
- .show = load_seq_show,
- .stop = smk_seq_stop,
-};
-
-/**
- * smk_open_load - open() for /smack/load
- * @inode: inode structure representing file
- * @file: "load" file pointer
- *
- * For reading, use load_seq_* seq_file reading operations.
- */
-static int smk_open_load(struct inode *inode, struct file *file)
-{
- return seq_open(file, &load_seq_ops);
-}
-
-/**
- * smk_write_load - write() for /smack/load
- * @file: file pointer, not actually used
- * @buf: where to get the data from
- * @count: bytes sent
- * @ppos: where to start - must be 0
- *
- */
-static ssize_t smk_write_load(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
-
- /*
- * Must have privilege.
- * No partial writes.
- * Enough data must be present.
- */
- if (!capable(CAP_MAC_ADMIN))
- return -EPERM;
-
- return smk_write_load_list(file, buf, count, ppos, NULL, NULL);
-}
-
-static const struct file_operations smk_load_ops = {
- .open = smk_open_load,
- .read = seq_read,
- .llseek = seq_lseek,
- .write = smk_write_load,
- .release = seq_release,
-};
-
-/**
- * smk_cipso_doi - initialize the CIPSO domain
- */
-static void smk_cipso_doi(void)
-{
- int rc;
- struct cipso_v4_doi *doip;
- struct netlbl_audit nai;
-
- smk_netlabel_audit_set(&nai);
-
- rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
- if (rc != 0)
- printk(KERN_WARNING "%s:%d remove rc = %d\n",
- __func__, __LINE__, rc);
-
- doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL);
- if (doip == NULL)
- panic("smack: Failed to initialize cipso DOI.\n");
- doip->map.std = NULL;
- doip->doi = smk_cipso_doi_value;
- doip->type = CIPSO_V4_MAP_PASS;
- doip->tags[0] = CIPSO_V4_TAG_RBITMAP;
- for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)
- doip->tags[rc] = CIPSO_V4_TAG_INVALID;
-
- rc = netlbl_cfg_cipsov4_add(doip, &nai);
- if (rc != 0) {
- printk(KERN_WARNING "%s:%d cipso add rc = %d\n",
- __func__, __LINE__, rc);
- kfree(doip);
- return;
- }
- rc = netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai);
- if (rc != 0) {
- printk(KERN_WARNING "%s:%d map add rc = %d\n",
- __func__, __LINE__, rc);
- kfree(doip);
- return;
- }
-}
-
-/**
- * smk_unlbl_ambient - initialize the unlabeled domain
- * @oldambient: previous domain string
- */
-static void smk_unlbl_ambient(char *oldambient)
-{
- int rc;
- struct netlbl_audit nai;
-
- smk_netlabel_audit_set(&nai);
-
- if (oldambient != NULL) {
- rc = netlbl_cfg_map_del(oldambient, PF_INET, NULL, NULL, &nai);
- if (rc != 0)
- printk(KERN_WARNING "%s:%d remove rc = %d\n",
- __func__, __LINE__, rc);
- }
-
- rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET,
- NULL, NULL, &nai);
- if (rc != 0)
- printk(KERN_WARNING "%s:%d add rc = %d\n",
- __func__, __LINE__, rc);
-}
-
-/*
- * Seq_file read operations for /smack/cipso
- */
-
-static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
-{
- return smk_seq_start(s, pos, &smack_known_list);
-}
-
-static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
- return smk_seq_next(s, v, pos, &smack_known_list);
-}
-
-/*
- * Print cipso labels in format:
- * label level[/cat[,cat]]
- */
-static int cipso_seq_show(struct seq_file *s, void *v)
-{
- struct list_head *list = v;
- struct smack_known *skp =
- list_entry(list, struct smack_known, list);
- struct smack_cipso *scp = skp->smk_cipso;
- char *cbp;
- char sep = '/';
- int cat = 1;
- int i;
- unsigned char m;
-
- if (scp == NULL)
- return 0;
-
- seq_printf(s, "%s %3d", (char *)&skp->smk_known, scp->smk_level);
-
- cbp = scp->smk_catset;
- for (i = 0; i < SMK_LABELLEN; i++)
- for (m = 0x80; m != 0; m >>= 1) {
- if (m & cbp[i]) {
- seq_printf(s, "%c%d", sep, cat);
- sep = ',';
- }
- cat++;
- }
-
- seq_putc(s, '\n');
-
- return 0;
-}
-
-static const struct seq_operations cipso_seq_ops = {
- .start = cipso_seq_start,
- .next = cipso_seq_next,
- .show = cipso_seq_show,
- .stop = smk_seq_stop,
-};
-
-/**
- * smk_open_cipso - open() for /smack/cipso
- * @inode: inode structure representing file
- * @file: "cipso" file pointer
- *
- * Connect our cipso_seq_* operations with /smack/cipso
- * file_operations
- */
-static int smk_open_cipso(struct inode *inode, struct file *file)
-{
- return seq_open(file, &cipso_seq_ops);
-}
-
-/**
- * smk_write_cipso - write() for /smack/cipso
- * @file: file pointer, not actually used
- * @buf: where to get the data from
- * @count: bytes sent
- * @ppos: where to start
- *
- * Accepts only one cipso rule per write call.
- * Returns number of bytes written or error code, as appropriate
- */
-static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct smack_known *skp;
- struct smack_cipso *scp = NULL;
- char mapcatset[SMK_LABELLEN];
- int maplevel;
- int cat;
- int catlen;
- ssize_t rc = -EINVAL;
- char *data = NULL;
- char *rule;
- int ret;
- int i;
-
- /*
- * Must have privilege.
- * No partial writes.
- * Enough data must be present.
- */
- if (!capable(CAP_MAC_ADMIN))
- return -EPERM;
- if (*ppos != 0)
- return -EINVAL;
- if (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX)
- return -EINVAL;
-
- data = kzalloc(count + 1, GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(data, buf, count) != 0) {
- rc = -EFAULT;
- goto unlockedout;
- }
-
- /* labels cannot begin with a '-' */
- if (data[0] == '-') {
- rc = -EINVAL;
- goto unlockedout;
- }
- data[count] = '\0';
- rule = data;
- /*
- * Only allow one writer at a time. Writes should be
- * quite rare and small in any case.
- */
- mutex_lock(&smack_cipso_lock);
-
- skp = smk_import_entry(rule, 0);
- if (skp == NULL)
- goto out;
-
- rule += SMK_LABELLEN;
- ret = sscanf(rule, "%d", &maplevel);
- if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL)
- goto out;
-
- rule += SMK_DIGITLEN;
- ret = sscanf(rule, "%d", &catlen);
- if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
- goto out;
-
- if (count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
- goto out;
-
- memset(mapcatset, 0, sizeof(mapcatset));
-
- for (i = 0; i < catlen; i++) {
- rule += SMK_DIGITLEN;
- ret = sscanf(rule, "%d", &cat);
- if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL)
- goto out;
-
- smack_catset_bit(cat, mapcatset);
- }
-
- if (skp->smk_cipso == NULL) {
- scp = kzalloc(sizeof(struct smack_cipso), GFP_KERNEL);
- if (scp == NULL) {
- rc = -ENOMEM;
- goto out;
- }
- }
-
- spin_lock_bh(&skp->smk_cipsolock);
-
- if (scp == NULL)
- scp = skp->smk_cipso;
- else
- skp->smk_cipso = scp;
-
- scp->smk_level = maplevel;
- memcpy(scp->smk_catset, mapcatset, sizeof(mapcatset));
-
- spin_unlock_bh(&skp->smk_cipsolock);
-
- rc = count;
-out:
- mutex_unlock(&smack_cipso_lock);
-unlockedout:
- kfree(data);
- return rc;
-}
-
-static const struct file_operations smk_cipso_ops = {
- .open = smk_open_cipso,
- .read = seq_read,
- .llseek = seq_lseek,
- .write = smk_write_cipso,
- .release = seq_release,
-};
-
-/*
- * Seq_file read operations for /smack/netlabel
- */
-
-static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
-{
- return smk_seq_start(s, pos, &smk_netlbladdr_list);
-}
-
-static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
- return smk_seq_next(s, v, pos, &smk_netlbladdr_list);
-}
-#define BEBITS (sizeof(__be32) * 8)
-
-/*
- * Print host/label pairs
- */
-static int netlbladdr_seq_show(struct seq_file *s, void *v)
-{
- struct list_head *list = v;
- struct smk_netlbladdr *skp =
- list_entry(list, struct smk_netlbladdr, list);
- unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
- int maskn;
- u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
-
- for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++);
-
- seq_printf(s, "%u.%u.%u.%u/%d %s\n",
- hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);
-
- return 0;
-}
-
-static const struct seq_operations netlbladdr_seq_ops = {
- .start = netlbladdr_seq_start,
- .next = netlbladdr_seq_next,
- .show = netlbladdr_seq_show,
- .stop = smk_seq_stop,
-};
-
-/**
- * smk_open_netlbladdr - open() for /smack/netlabel
- * @inode: inode structure representing file
- * @file: "netlabel" file pointer
- *
- * Connect our netlbladdr_seq_* operations with /smack/netlabel
- * file_operations
- */
-static int smk_open_netlbladdr(struct inode *inode, struct file *file)
-{
- return seq_open(file, &netlbladdr_seq_ops);
-}
-
-/**
- * smk_netlbladdr_insert
- * @new : netlabel to insert
- *
- * This helper insert netlabel in the smack_netlbladdrs list
- * sorted by netmask length (longest to smallest)
- * locked by &smk_netlbladdr_lock in smk_write_netlbladdr
- *
- */
-static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
-{
- struct smk_netlbladdr *m, *m_next;
-
- if (list_empty(&smk_netlbladdr_list)) {
- list_add_rcu(&new->list, &smk_netlbladdr_list);
- return;
- }
-
- m = list_entry_rcu(smk_netlbladdr_list.next,
- struct smk_netlbladdr, list);
-
- /* the comparison '>' is a bit hacky, but works */
- if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
- list_add_rcu(&new->list, &smk_netlbladdr_list);
- return;
- }
-
- list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) {
- if (list_is_last(&m->list, &smk_netlbladdr_list)) {
- list_add_rcu(&new->list, &m->list);
- return;
- }
- m_next = list_entry_rcu(m->list.next,
- struct smk_netlbladdr, list);
- if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) {
- list_add_rcu(&new->list, &m->list);
- return;
- }
- }
-}
-
-
-/**
- * smk_write_netlbladdr - write() for /smack/netlabel
- * @file: file pointer, not actually used
- * @buf: where to get the data from
- * @count: bytes sent
- * @ppos: where to start
- *
- * Accepts only one netlbladdr per write call.
- * Returns number of bytes written or error code, as appropriate
- */
-static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct smk_netlbladdr *skp;
- struct sockaddr_in newname;
- char smack[SMK_LABELLEN];
- char *sp;
- char data[SMK_NETLBLADDRMAX + 1];
- char *host = (char *)&newname.sin_addr.s_addr;
- int rc;
- struct netlbl_audit audit_info;
- struct in_addr mask;
- unsigned int m;
- int found;
- u32 mask_bits = (1<<31);
- __be32 nsa;
- u32 temp_mask;
-
- /*
- * Must have privilege.
- * No partial writes.
- * Enough data must be present.
- * "<addr/mask, as a.b.c.d/e><space><label>"
- * "<addr, as a.b.c.d><space><label>"
- */
- if (!capable(CAP_MAC_ADMIN))
- return -EPERM;
- if (*ppos != 0)
- return -EINVAL;
- if (count < SMK_NETLBLADDRMIN || count > SMK_NETLBLADDRMAX)
- return -EINVAL;
- if (copy_from_user(data, buf, count) != 0)
- return -EFAULT;
-
- data[count] = '\0';
-
- rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%d %s",
- &host[0], &host[1], &host[2], &host[3], &m, smack);
- if (rc != 6) {
- rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
- &host[0], &host[1], &host[2], &host[3], smack);
- if (rc != 5)
- return -EINVAL;
- m = BEBITS;
- }
- if (m > BEBITS)
- return -EINVAL;
-
- /* if smack begins with '-', its an option, don't import it */
- if (smack[0] != '-') {
- sp = smk_import(smack, 0);
- if (sp == NULL)
- return -EINVAL;
- } else {
- /* check known options */
- if (strcmp(smack, smack_cipso_option) == 0)
- sp = (char *)smack_cipso_option;
- else
- return -EINVAL;
- }
-
- for (temp_mask = 0; m > 0; m--) {
- temp_mask |= mask_bits;
- mask_bits >>= 1;
- }
- mask.s_addr = cpu_to_be32(temp_mask);
-
- newname.sin_addr.s_addr &= mask.s_addr;
- /*
- * Only allow one writer at a time. Writes should be
- * quite rare and small in any case.
- */
- mutex_lock(&smk_netlbladdr_lock);
-
- nsa = newname.sin_addr.s_addr;
- /* try to find if the prefix is already in the list */
- found = 0;
- list_for_each_entry_rcu(skp, &smk_netlbladdr_list, list) {
- if (skp->smk_host.sin_addr.s_addr == nsa &&
- skp->smk_mask.s_addr == mask.s_addr) {
- found = 1;
- break;
- }
- }
- smk_netlabel_audit_set(&audit_info);
-
- if (found == 0) {
- skp = kzalloc(sizeof(*skp), GFP_KERNEL);
- if (skp == NULL)
- rc = -ENOMEM;
- else {
- rc = 0;
- skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
- skp->smk_mask.s_addr = mask.s_addr;
- skp->smk_label = sp;
- smk_netlbladdr_insert(skp);
- }
- } else {
- /* we delete the unlabeled entry, only if the previous label
- * wasn't the special CIPSO option */
- if (skp->smk_label != smack_cipso_option)
- rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
- &skp->smk_host.sin_addr, &skp->smk_mask,
- PF_INET, &audit_info);
- else
- rc = 0;
- skp->smk_label = sp;
- }
-
- /*
- * Now tell netlabel about the single label nature of
- * this host so that incoming packets get labeled.
- * but only if we didn't get the special CIPSO option
- */
- if (rc == 0 && sp != smack_cipso_option)
- rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
- &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
- smack_to_secid(skp->smk_label), &audit_info);
-
- if (rc == 0)
- rc = count;
-
- mutex_unlock(&smk_netlbladdr_lock);
-
- return rc;
-}
-
-static const struct file_operations smk_netlbladdr_ops = {
- .open = smk_open_netlbladdr,
- .read = seq_read,
- .llseek = seq_lseek,
- .write = smk_write_netlbladdr,
- .release = seq_release,
-};
-
-/**
- * smk_read_doi - read() for /smack/doi
- * @filp: file pointer, not actually used
- * @buf: where to put the result
- * @count: maximum to send along
- * @ppos: where to start
- *
- * Returns number of bytes read or error code, as appropriate
- */
-static ssize_t smk_read_doi(struct file *filp, char __user *buf,
- size_t count, loff_t *ppos)
-{
- char temp[80];
- ssize_t rc;
-
- if (*ppos != 0)
- return 0;
-
- sprintf(temp, "%d", smk_cipso_doi_value);
- rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
-
- return rc;
-}
-
-/**
- * smk_write_doi - write() for /smack/doi
- * @file: file pointer, not actually used
- * @buf: where to get the data from
- * @count: bytes sent
- * @ppos: where to start
- *
- * Returns number of bytes written or error code, as appropriate
- */
-static ssize_t smk_write_doi(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- char temp[80];
- int i;
-
- if (!capable(CAP_MAC_ADMIN))
- return -EPERM;
-
- if (count >= sizeof(temp) || count == 0)
- return -EINVAL;
-
- if (copy_from_user(temp, buf, count) != 0)
- return -EFAULT;
-
- temp[count] = '\0';
-
- if (sscanf(temp, "%d", &i) != 1)
- return -EINVAL;
-
- smk_cipso_doi_value = i;
-
- smk_cipso_doi();
-
- return count;
-}
-
-static const struct file_operations smk_doi_ops = {
- .read = smk_read_doi,
- .write = smk_write_doi,
- .llseek = default_llseek,
-};
-
-/**
- * smk_read_direct - read() for /smack/direct
- * @filp: file pointer, not actually used
- * @buf: where to put the result
- * @count: maximum to send along
- * @ppos: where to start
- *
- * Returns number of bytes read or error code, as appropriate
- */
-static ssize_t smk_read_direct(struct file *filp, char __user *buf,
- size_t count, loff_t *ppos)
-{
- char temp[80];
- ssize_t rc;
-
- if (*ppos != 0)
- return 0;
-
- sprintf(temp, "%d", smack_cipso_direct);
- rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
-
- return rc;
-}
-
-/**
- * smk_write_direct - write() for /smack/direct
- * @file: file pointer, not actually used
- * @buf: where to get the data from
- * @count: bytes sent
- * @ppos: where to start
- *
- * Returns number of bytes written or error code, as appropriate
- */
-static ssize_t smk_write_direct(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- char temp[80];
- int i;
-
- if (!capable(CAP_MAC_ADMIN))
- return -EPERM;
-
- if (count >= sizeof(temp) || count == 0)
- return -EINVAL;
-
- if (copy_from_user(temp, buf, count) != 0)
- return -EFAULT;
-
- temp[count] = '\0';
-
- if (sscanf(temp, "%d", &i) != 1)
- return -EINVAL;
-
- smack_cipso_direct = i;
-
- return count;
-}
-
-static const struct file_operations smk_direct_ops = {
- .read = smk_read_direct,
- .write = smk_write_direct,
- .llseek = default_llseek,
-};
-
-/**
- * smk_read_ambient - read() for /smack/ambient
- * @filp: file pointer, not actually used
- * @buf: where to put the result
- * @cn: maximum to send along
- * @ppos: where to start
- *
- * Returns number of bytes read or error code, as appropriate
- */
-static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
- size_t cn, loff_t *ppos)
-{
- ssize_t rc;
- int asize;
-
- if (*ppos != 0)
- return 0;
- /*
- * Being careful to avoid a problem in the case where
- * smack_net_ambient gets changed in midstream.
- */
- mutex_lock(&smack_ambient_lock);
-
- asize = strlen(smack_net_ambient) + 1;
-
- if (cn >= asize)
- rc = simple_read_from_buffer(buf, cn, ppos,
- smack_net_ambient, asize);
- else
- rc = -EINVAL;
-
- mutex_unlock(&smack_ambient_lock);
-
- return rc;
-}
-
-/**
- * smk_write_ambient - write() for /smack/ambient
- * @file: file pointer, not actually used
- * @buf: where to get the data from
- * @count: bytes sent
- * @ppos: where to start
- *
- * Returns number of bytes written or error code, as appropriate
- */
-static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- char in[SMK_LABELLEN];
- char *oldambient;
- char *smack;
-
- if (!capable(CAP_MAC_ADMIN))
- return -EPERM;
-
- if (count >= SMK_LABELLEN)
- return -EINVAL;
-
- if (copy_from_user(in, buf, count) != 0)
- return -EFAULT;
-
- smack = smk_import(in, count);
- if (smack == NULL)
- return -EINVAL;
-
- mutex_lock(&smack_ambient_lock);
-
- oldambient = smack_net_ambient;
- smack_net_ambient = smack;
- smk_unlbl_ambient(oldambient);
-
- mutex_unlock(&smack_ambient_lock);
-
- return count;
-}
-
-static const struct file_operations smk_ambient_ops = {
- .read = smk_read_ambient,
- .write = smk_write_ambient,
- .llseek = default_llseek,
-};
-
-/**
- * smk_read_onlycap - read() for /smack/onlycap
- * @filp: file pointer, not actually used
- * @buf: where to put the result
- * @cn: maximum to send along
- * @ppos: where to start
- *
- * Returns number of bytes read or error code, as appropriate
- */
-static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
- size_t cn, loff_t *ppos)
-{
- char *smack = "";
- ssize_t rc = -EINVAL;
- int asize;
-
- if (*ppos != 0)
- return 0;
-
- if (smack_onlycap != NULL)
- smack = smack_onlycap;
-
- asize = strlen(smack) + 1;
-
- if (cn >= asize)
- rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
-
- return rc;
-}
-
-/**
- * smk_write_onlycap - write() for /smack/onlycap
- * @file: file pointer, not actually used
- * @buf: where to get the data from
- * @count: bytes sent
- * @ppos: where to start
- *
- * Returns number of bytes written or error code, as appropriate
- */
-static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- char in[SMK_LABELLEN];
- char *sp = smk_of_task(current->cred->security);
-
- if (!capable(CAP_MAC_ADMIN))
- return -EPERM;
-
- /*
- * This can be done using smk_access() but is done
- * explicitly for clarity. The smk_access() implementation
- * would use smk_access(smack_onlycap, MAY_WRITE)
- */
- if (smack_onlycap != NULL && smack_onlycap != sp)
- return -EPERM;
-
- if (count >= SMK_LABELLEN)
- return -EINVAL;
-
- if (copy_from_user(in, buf, count) != 0)
- return -EFAULT;
-
- /*
- * Should the null string be passed in unset the onlycap value.
- * This seems like something to be careful with as usually
- * smk_import only expects to return NULL for errors. It
- * is usually the case that a nullstring or "\n" would be
- * bad to pass to smk_import but in fact this is useful here.
- */
- smack_onlycap = smk_import(in, count);
-
- return count;
-}
-
-static const struct file_operations smk_onlycap_ops = {
- .read = smk_read_onlycap,
- .write = smk_write_onlycap,
- .llseek = default_llseek,
-};
-
-/**
- * smk_read_logging - read() for /smack/logging
- * @filp: file pointer, not actually used
- * @buf: where to put the result
- * @cn: maximum to send along
- * @ppos: where to start
- *
- * Returns number of bytes read or error code, as appropriate
- */
-static ssize_t smk_read_logging(struct file *filp, char __user *buf,
- size_t count, loff_t *ppos)
-{
- char temp[32];
- ssize_t rc;
-
- if (*ppos != 0)
- return 0;
-
- sprintf(temp, "%d\n", log_policy);
- rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
- return rc;
-}
-
-/**
- * smk_write_logging - write() for /smack/logging
- * @file: file pointer, not actually used
- * @buf: where to get the data from
- * @count: bytes sent
- * @ppos: where to start
- *
- * Returns number of bytes written or error code, as appropriate
- */
-static ssize_t smk_write_logging(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- char temp[32];
- int i;
-
- if (!capable(CAP_MAC_ADMIN))
- return -EPERM;
-
- if (count >= sizeof(temp) || count == 0)
- return -EINVAL;
-
- if (copy_from_user(temp, buf, count) != 0)
- return -EFAULT;
-
- temp[count] = '\0';
-
- if (sscanf(temp, "%d", &i) != 1)
- return -EINVAL;
- if (i < 0 || i > 3)
- return -EINVAL;
- log_policy = i;
- return count;
-}
-
-
-
-static const struct file_operations smk_logging_ops = {
- .read = smk_read_logging,
- .write = smk_write_logging,
- .llseek = default_llseek,
-};
-
-/*
- * Seq_file read operations for /smack/load-self
- */
-
-static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
-{
- struct task_smack *tsp = current_security();
-
- return smk_seq_start(s, pos, &tsp->smk_rules);
-}
-
-static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
- struct task_smack *tsp = current_security();
-
- return smk_seq_next(s, v, pos, &tsp->smk_rules);
-}
-
-static int load_self_seq_show(struct seq_file *s, void *v)
-{
- struct list_head *list = v;
- struct smack_rule *srp =
- list_entry(list, struct smack_rule, list);
-
- seq_printf(s, "%s %s", (char *)srp->smk_subject,
- (char *)srp->smk_object);
-
- seq_putc(s, ' ');
-
- if (srp->smk_access & MAY_READ)
- seq_putc(s, 'r');
- if (srp->smk_access & MAY_WRITE)
- seq_putc(s, 'w');
- if (srp->smk_access & MAY_EXEC)
- seq_putc(s, 'x');
- if (srp->smk_access & MAY_APPEND)
- seq_putc(s, 'a');
- if (srp->smk_access & MAY_TRANSMUTE)
- seq_putc(s, 't');
- if (srp->smk_access == 0)
- seq_putc(s, '-');
-
- seq_putc(s, '\n');
-
- return 0;
-}
-
-static const struct seq_operations load_self_seq_ops = {
- .start = load_self_seq_start,
- .next = load_self_seq_next,
- .show = load_self_seq_show,
- .stop = smk_seq_stop,
-};
-
-
-/**
- * smk_open_load_self - open() for /smack/load-self
- * @inode: inode structure representing file
- * @file: "load" file pointer
- *
- * For reading, use load_seq_* seq_file reading operations.
- */
-static int smk_open_load_self(struct inode *inode, struct file *file)
-{
- return seq_open(file, &load_self_seq_ops);
-}
-
-/**
- * smk_write_load_self - write() for /smack/load-self
- * @file: file pointer, not actually used
- * @buf: where to get the data from
- * @count: bytes sent
- * @ppos: where to start - must be 0
- *
- */
-static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct task_smack *tsp = current_security();
-
- return smk_write_load_list(file, buf, count, ppos, &tsp->smk_rules,
- &tsp->smk_rules_lock);
-}
-
-static const struct file_operations smk_load_self_ops = {
- .open = smk_open_load_self,
- .read = seq_read,
- .llseek = seq_lseek,
- .write = smk_write_load_self,
- .release = seq_release,
-};
-
-/**
- * smk_write_access - handle access check transaction
- * @file: file pointer
- * @buf: data from user space
- * @count: bytes sent
- * @ppos: where to start - must be 0
- */
-static ssize_t smk_write_access(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct smack_rule rule;
- char *data;
- int res;
-
- data = simple_transaction_get(file, buf, count);
- if (IS_ERR(data))
- return PTR_ERR(data);
-
- if (count < SMK_LOADLEN || smk_parse_rule(data, &rule, 0))
- return -EINVAL;
-
- res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access,
- NULL);
- data[0] = res == 0 ? '1' : '0';
- data[1] = '\0';
-
- simple_transaction_set(file, 2);
- return SMK_LOADLEN;
-}
-
-static const struct file_operations smk_access_ops = {
- .write = smk_write_access,
- .read = simple_transaction_read,
- .release = simple_transaction_release,
- .llseek = generic_file_llseek,
-};
-
-/**
- * smk_fill_super - fill the /smackfs superblock
- * @sb: the empty superblock
- * @data: unused
- * @silent: unused
- *
- * Fill in the well known entries for /smack
- *
- * Returns 0 on success, an error code on failure
- */
-static int smk_fill_super(struct super_block *sb, void *data, int silent)
-{
- int rc;
- struct inode *root_inode;
-
- static struct tree_descr smack_files[] = {
- [SMK_LOAD] = {
- "load", &smk_load_ops, S_IRUGO|S_IWUSR},
- [SMK_CIPSO] = {
- "cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR},
- [SMK_DOI] = {
- "doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
- [SMK_DIRECT] = {
- "direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
- [SMK_AMBIENT] = {
- "ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
- [SMK_NETLBLADDR] = {
- "netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
- [SMK_ONLYCAP] = {
- "onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
- [SMK_LOGGING] = {
- "logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
- [SMK_LOAD_SELF] = {
- "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
- [SMK_ACCESSES] = {
- "access", &smk_access_ops, S_IRUGO|S_IWUGO},
- /* last one */
- {""}
- };
-
- rc = simple_fill_super(sb, SMACK_MAGIC, smack_files);
- if (rc != 0) {
- printk(KERN_ERR "%s failed %d while creating inodes\n",
- __func__, rc);
- return rc;
- }
-
- root_inode = sb->s_root->d_inode;
- root_inode->i_security = new_inode_smack(smack_known_floor.smk_known);
-
- return 0;
-}
-
-/**
- * smk_mount - get the smackfs superblock
- * @fs_type: passed along without comment
- * @flags: passed along without comment
- * @dev_name: passed along without comment
- * @data: passed along without comment
- *
- * Just passes everything along.
- *
- * Returns what the lower level code does.
- */
-static struct dentry *smk_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
-{
- return mount_single(fs_type, flags, data, smk_fill_super);
-}
-
-static struct file_system_type smk_fs_type = {
- .name = "smackfs",
- .mount = smk_mount,
- .kill_sb = kill_litter_super,
-};
-
-static struct vfsmount *smackfs_mount;
-
-/**
- * init_smk_fs - get the smackfs superblock
- *
- * register the smackfs
- *
- * Do not register smackfs if Smack wasn't enabled
- * on boot. We can not put this method normally under the
- * smack_init() code path since the security subsystem get
- * initialized before the vfs caches.
- *
- * Returns true if we were not chosen on boot or if
- * we were chosen and filesystem registration succeeded.
- */
-static int __init init_smk_fs(void)
-{
- int err;
-
- if (!security_module_enable(&smack_ops))
- return 0;
-
- err = register_filesystem(&smk_fs_type);
- if (!err) {
- smackfs_mount = kern_mount(&smk_fs_type);
- if (IS_ERR(smackfs_mount)) {
- printk(KERN_ERR "smackfs: could not mount!\n");
- err = PTR_ERR(smackfs_mount);
- smackfs_mount = NULL;
- }
- }
-
- smk_cipso_doi();
- smk_unlbl_ambient(NULL);
-
- return err;
-}
-
-__initcall(init_smk_fs);