// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2007 Casey Schaufler <[email protected]> * * Authors: * Casey Schaufler <[email protected]> * Ahmed S. Darwish <[email protected]> * * Special thanks to the authors of selinuxfs. * * Karl MacMillan <[email protected]> * James Morris <[email protected]> */ #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/cipso_ipv4.h> #include <linux/seq_file.h> #include <linux/ctype.h> #include <linux/audit.h> #include <linux/magic.h> #include <linux/mount.h> #include <linux/fs_context.h> #include "smack.h" #define BEBITS … /* * smackfs pseudo filesystem. */ enum smk_inos { … }; /* * List locks */ static DEFINE_MUTEX(smack_cipso_lock); static DEFINE_MUTEX(smack_ambient_lock); static DEFINE_MUTEX(smk_net4addr_lock); #if IS_ENABLED(CONFIG_IPV6) static DEFINE_MUTEX(smk_net6addr_lock); #endif /* CONFIG_IPV6 */ /* * This is the "ambient" label for network traffic. * If it isn't somehow marked, use this. * It can be reset via smackfs/ambient */ struct smack_known *smack_net_ambient; /* * 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 = …; /* * This is the level in a CIPSO header that indicates a * secid is contained directly in the category set. * It can be reset via smackfs/mapped */ int smack_cipso_mapped = …; #ifdef CONFIG_SECURITY_SMACK_BRINGUP /* * Allow one label to be unconfined. This is for * debugging and application bring-up purposes only. * It is bad and wrong, but everyone seems to expect * to have it. */ struct smack_known *smack_unconfined; #endif /* * If this value is set restrict syslog use to the label specified. * It can be reset via smackfs/syslog */ struct smack_known *smack_syslog_label; /* * Ptrace current rule * SMACK_PTRACE_DEFAULT regular smack ptrace rules (/proc based) * SMACK_PTRACE_EXACT labels must match, but can be overriden with * CAP_SYS_PTRACE * SMACK_PTRACE_DRACONIAN labels must match, CAP_SYS_PTRACE has no effect */ int smack_ptrace_rule = …; /* * 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(…); #if IS_ENABLED(CONFIG_IPV6) LIST_HEAD(…); #endif /* CONFIG_IPV6 */ /* * Rule lists are maintained for each label. */ struct smack_parsed_rule { … }; static int smk_cipso_doi_value = …; /* * 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 … #define SMK_CIPSOMIN … #define SMK_CIPSOMAX … /* * 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 … #define SMK_ACCESS … #define SMK_OACCESSLEN … #define SMK_ACCESSLEN … #define SMK_OLOADLEN … #define SMK_LOADLEN … /* * Stricly for CIPSO level manipulation. * Set the category bit number in a smack label sized buffer. */ static inline void smack_catset_bit(unsigned int cat, char *catsetp) { … } /** * smk_netlabel_audit_set - fill a netlbl_audit struct * @nap: structure to fill */ static void smk_netlabel_audit_set(struct netlbl_audit *nap) { … } /* * Value for parsing single label host rules * "1.2.3.4 X" */ #define SMK_NETLBLADDRMIN … /** * smk_set_access - add a rule to the rule list or replace an old rule * @srp: the rule to add or replace * @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 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_parsed_rule *srp, struct list_head *rule_list, struct mutex *rule_lock) { … } /** * smk_perm_from_str - parse smack accesses from a text string * @string: a text string that contains a Smack accesses code * * Returns an integer with respective bits set for specified accesses. */ static int smk_perm_from_str(const char *string) { … } /** * smk_fill_rule - Fill Smack rule from strings * @subject: subject label string * @object: object label string * @access1: access string * @access2: string with permissions to be removed * @rule: Smack rule * @import: if non-zero, import labels * @len: label length limit * * Returns 0 on success, appropriate error code on failure. */ static int smk_fill_rule(const char *subject, const char *object, const char *access1, const char *access2, struct smack_parsed_rule *rule, int import, int len) { … } /** * 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 * * Returns 0 on success, -1 on errors. */ static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule, int import) { … } /** * smk_parse_long_rule - parse Smack rule from rule string * @data: string to be parsed, null terminated * @rule: Will be filled with Smack parsed rule * @import: if non-zero, import labels * @tokens: number of substrings expected in data * * Returns number of processed bytes on success, -ERRNO on failure. */ static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule, int import, int tokens) { … } #define SMK_FIXED24_FMT … #define SMK_LONG_FMT … #define SMK_CHANGE_FMT … /** * smk_write_rules_list - write() for any /smack rule file * @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 * @format: /smack/load or /smack/load2 or /smack/change-rule format. * * Get one smack access rule from above. * The format for SMK_LONG_FMT is: * "subject<whitespace>object<whitespace>access[<whitespace>...]" * The format for SMK_FIXED24_FMT is exactly: * "subject object rwxat" * The format for SMK_CHANGE_FMT is: * "subject<whitespace>object<whitespace> * acc_enable<whitespace>acc_disable[<whitespace>...]" */ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, size_t count, loff_t *ppos, struct list_head *rule_list, struct mutex *rule_lock, int format) { … } /* * Core logic for smackfs seq list operations. */ static void *smk_seq_start(struct seq_file *s, loff_t *pos, struct list_head *head) { … } static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos, struct list_head *head) { … } static void smk_seq_stop(struct seq_file *s, void *v) { … } static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) { … } /* * Seq_file read operations for /smack/load */ static void *load2_seq_start(struct seq_file *s, loff_t *pos) { … } static void *load2_seq_next(struct seq_file *s, void *v, loff_t *pos) { … } static int load_seq_show(struct seq_file *s, void *v) { … } static const struct seq_operations load_seq_ops = …; /** * 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) { … } /** * 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) { … } static const struct file_operations smk_load_ops = …; /** * smk_cipso_doi - initialize the CIPSO domain */ static void smk_cipso_doi(void) { … } /** * smk_unlbl_ambient - initialize the unlabeled domain * @oldambient: previous domain string */ static void smk_unlbl_ambient(char *oldambient) { … } /* * Seq_file read operations for /smack/cipso */ static void *cipso_seq_start(struct seq_file *s, loff_t *pos) { … } static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos) { … } /* * Print cipso labels in format: * label level[/cat[,cat]] */ static int cipso_seq_show(struct seq_file *s, void *v) { … } static const struct seq_operations cipso_seq_ops = …; /** * 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) { … } /** * smk_set_cipso - do the work for write() for cipso and cipso2 * @file: file pointer, not actually used * @buf: where to get the data from * @count: bytes sent * @ppos: where to start * @format: /smack/cipso or /smack/cipso2 * * Accepts only one cipso rule per write call. * Returns number of bytes written or error code, as appropriate */ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, size_t count, loff_t *ppos, int format) { … } /** * 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) { … } static const struct file_operations smk_cipso_ops = …; /* * Seq_file read operations for /smack/cipso2 */ /* * Print cipso labels in format: * label level[/cat[,cat]] */ static int cipso2_seq_show(struct seq_file *s, void *v) { … } static const struct seq_operations cipso2_seq_ops = …; /** * smk_open_cipso2 - open() for /smack/cipso2 * @inode: inode structure representing file * @file: "cipso2" file pointer * * Connect our cipso_seq_* operations with /smack/cipso2 * file_operations */ static int smk_open_cipso2(struct inode *inode, struct file *file) { … } /** * smk_write_cipso2 - write() for /smack/cipso2 * @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_cipso2(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_cipso2_ops = …; /* * Seq_file read operations for /smack/netlabel */ static void *net4addr_seq_start(struct seq_file *s, loff_t *pos) { … } static void *net4addr_seq_next(struct seq_file *s, void *v, loff_t *pos) { … } /* * Print host/label pairs */ static int net4addr_seq_show(struct seq_file *s, void *v) { … } static const struct seq_operations net4addr_seq_ops = …; /** * smk_open_net4addr - open() for /smack/netlabel * @inode: inode structure representing file * @file: "netlabel" file pointer * * Connect our net4addr_seq_* operations with /smack/netlabel * file_operations */ static int smk_open_net4addr(struct inode *inode, struct file *file) { … } /** * smk_net4addr_insert * @new : netlabel to insert * * This helper insert netlabel in the smack_net4addrs list * sorted by netmask length (longest to smallest) * locked by &smk_net4addr_lock in smk_write_net4addr * */ static void smk_net4addr_insert(struct smk_net4addr *new) { … } /** * smk_write_net4addr - 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 net4addr per write call. * Returns number of bytes written or error code, as appropriate */ static ssize_t smk_write_net4addr(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_net4addr_ops = …; #if IS_ENABLED(CONFIG_IPV6) /* * Seq_file read operations for /smack/netlabel6 */ static void *net6addr_seq_start(struct seq_file *s, loff_t *pos) { … } static void *net6addr_seq_next(struct seq_file *s, void *v, loff_t *pos) { … } /* * Print host/label pairs */ static int net6addr_seq_show(struct seq_file *s, void *v) { … } static const struct seq_operations net6addr_seq_ops = …; /** * smk_open_net6addr - open() for /smack/netlabel * @inode: inode structure representing file * @file: "netlabel" file pointer * * Connect our net6addr_seq_* operations with /smack/netlabel * file_operations */ static int smk_open_net6addr(struct inode *inode, struct file *file) { … } /** * smk_net6addr_insert * @new : entry to insert * * This inserts an entry in the smack_net6addrs list * sorted by netmask length (longest to smallest) * locked by &smk_net6addr_lock in smk_write_net6addr * */ static void smk_net6addr_insert(struct smk_net6addr *new) { … } /** * smk_write_net6addr - 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 net6addr per write call. * Returns number of bytes written or error code, as appropriate */ static ssize_t smk_write_net6addr(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_net6addr_ops = …; #endif /* CONFIG_IPV6 */ /** * 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) { … } /** * 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) { … } static const struct file_operations smk_doi_ops = …; /** * 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) { … } /** * 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) { … } static const struct file_operations smk_direct_ops = …; /** * smk_read_mapped - read() for /smack/mapped * @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_mapped(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { … } /** * smk_write_mapped - write() for /smack/mapped * @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_mapped(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_mapped_ops = …; /** * 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) { … } /** * 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) { … } static const struct file_operations smk_ambient_ops = …; /* * Seq_file operations for /smack/onlycap */ static void *onlycap_seq_start(struct seq_file *s, loff_t *pos) { … } static void *onlycap_seq_next(struct seq_file *s, void *v, loff_t *pos) { … } static int onlycap_seq_show(struct seq_file *s, void *v) { … } static const struct seq_operations onlycap_seq_ops = …; static int smk_open_onlycap(struct inode *inode, struct file *file) { … } /** * smk_list_swap_rcu - swap public list with a private one in RCU-safe way * The caller must hold appropriate mutex to prevent concurrent modifications * to the public list. * Private list is assumed to be not accessible to other threads yet. * * @public: public list * @private: private list */ static void smk_list_swap_rcu(struct list_head *public, struct list_head *private) { … } /** * smk_parse_label_list - parse list of Smack labels, separated by spaces * * @data: the string to parse * @list: destination list * * Returns zero on success or error code, as appropriate */ static int smk_parse_label_list(char *data, struct list_head *list) { … } /** * smk_destroy_label_list - destroy a list of smack_known_list_elem * @list: header pointer of the list to destroy */ void smk_destroy_label_list(struct list_head *list) { … } /** * smk_write_onlycap - write() for smackfs/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) { … } static const struct file_operations smk_onlycap_ops = …; #ifdef CONFIG_SECURITY_SMACK_BRINGUP /** * smk_read_unconfined - read() for smackfs/unconfined * @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_unconfined(struct file *filp, char __user *buf, size_t cn, loff_t *ppos) { … } /** * smk_write_unconfined - write() for smackfs/unconfined * @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_unconfined(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_unconfined_ops = …; #endif /* CONFIG_SECURITY_SMACK_BRINGUP */ /** * smk_read_logging - read() for /smack/logging * @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_logging(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { … } /** * 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) { … } static const struct file_operations smk_logging_ops = …; /* * Seq_file read operations for /smack/load-self */ static void *load_self_seq_start(struct seq_file *s, loff_t *pos) { … } static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos) { … } static int load_self_seq_show(struct seq_file *s, void *v) { … } static const struct seq_operations load_self_seq_ops = …; /** * smk_open_load_self - open() for /smack/load-self2 * @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) { … } /** * 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) { … } static const struct file_operations smk_load_self_ops = …; /** * smk_user_access - handle access check transaction * @file: file pointer * @buf: data from user space * @count: bytes sent * @ppos: where to start - must be 0 * @format: /smack/load or /smack/load2 or /smack/change-rule format. */ static ssize_t smk_user_access(struct file *file, const char __user *buf, size_t count, loff_t *ppos, int format) { … } /** * 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) { … } static const struct file_operations smk_access_ops = …; /* * Seq_file read operations for /smack/load2 */ static int load2_seq_show(struct seq_file *s, void *v) { … } static const struct seq_operations load2_seq_ops = …; /** * smk_open_load2 - open() for /smack/load2 * @inode: inode structure representing file * @file: "load2" file pointer * * For reading, use load2_seq_* seq_file reading operations. */ static int smk_open_load2(struct inode *inode, struct file *file) { … } /** * smk_write_load2 - write() for /smack/load2 * @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_load2(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_load2_ops = …; /* * Seq_file read operations for /smack/load-self2 */ static void *load_self2_seq_start(struct seq_file *s, loff_t *pos) { … } static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos) { … } static int load_self2_seq_show(struct seq_file *s, void *v) { … } static const struct seq_operations load_self2_seq_ops = …; /** * smk_open_load_self2 - open() for /smack/load-self2 * @inode: inode structure representing file * @file: "load" file pointer * * For reading, use load_seq_* seq_file reading operations. */ static int smk_open_load_self2(struct inode *inode, struct file *file) { … } /** * smk_write_load_self2 - write() for /smack/load-self2 * @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_self2(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_load_self2_ops = …; /** * smk_write_access2 - 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_access2(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_access2_ops = …; /** * smk_write_revoke_subj - write() for /smack/revoke-subject * @file: file pointer * @buf: data from user space * @count: bytes sent * @ppos: where to start - must be 0 */ static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_revoke_subj_ops = …; /** * smk_init_sysfs - initialize /sys/fs/smackfs * */ static int smk_init_sysfs(void) { … } /** * smk_write_change_rule - write() for /smack/change-rule * @file: file pointer * @buf: data from user space * @count: bytes sent * @ppos: where to start - must be 0 */ static ssize_t smk_write_change_rule(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_change_rule_ops = …; /** * smk_read_syslog - read() for smackfs/syslog * @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_syslog(struct file *filp, char __user *buf, size_t cn, loff_t *ppos) { … } /** * smk_write_syslog - write() for smackfs/syslog * @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_syslog(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_syslog_ops = …; /* * Seq_file read operations for /smack/relabel-self */ static void *relabel_self_seq_start(struct seq_file *s, loff_t *pos) { … } static void *relabel_self_seq_next(struct seq_file *s, void *v, loff_t *pos) { … } static int relabel_self_seq_show(struct seq_file *s, void *v) { … } static const struct seq_operations relabel_self_seq_ops = …; /** * smk_open_relabel_self - open() for /smack/relabel-self * @inode: inode structure representing file * @file: "relabel-self" file pointer * * Connect our relabel_self_seq_* operations with /smack/relabel-self * file_operations */ static int smk_open_relabel_self(struct inode *inode, struct file *file) { … } /** * smk_write_relabel_self - write() for /smack/relabel-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_relabel_self(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_relabel_self_ops = …; /** * smk_read_ptrace - read() for /smack/ptrace * @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_ptrace(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { … } /** * smk_write_ptrace - write() for /smack/ptrace * @file: file pointer * @buf: data from user space * @count: bytes sent * @ppos: where to start - must be 0 */ static ssize_t smk_write_ptrace(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { … } static const struct file_operations smk_ptrace_ops = …; /** * smk_fill_super - fill the smackfs superblock * @sb: the empty superblock * @fc: unused * * Fill in the well known entries for the smack filesystem * * Returns 0 on success, an error code on failure */ static int smk_fill_super(struct super_block *sb, struct fs_context *fc) { … } /** * smk_get_tree - get the smackfs superblock * @fc: The mount context, including any options * * Just passes everything along. * * Returns what the lower level code does. */ static int smk_get_tree(struct fs_context *fc) { … } static const struct fs_context_operations smk_context_ops = …; /** * smk_init_fs_context - Initialise a filesystem context for smackfs * @fc: The blank mount context */ static int smk_init_fs_context(struct fs_context *fc) { … } static struct file_system_type smk_fs_type = …; 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) { … } __initcall(init_smk_fs);