19590837bSKentaro Takeda /* 29590837bSKentaro Takeda * security/tomoyo/common.h 39590837bSKentaro Takeda * 49590837bSKentaro Takeda * Common functions for TOMOYO. 59590837bSKentaro Takeda * 69590837bSKentaro Takeda * Copyright (C) 2005-2009 NTT DATA CORPORATION 79590837bSKentaro Takeda * 89590837bSKentaro Takeda * Version: 2.2.0-pre 2009/02/01 99590837bSKentaro Takeda * 109590837bSKentaro Takeda */ 119590837bSKentaro Takeda 129590837bSKentaro Takeda #ifndef _SECURITY_TOMOYO_COMMON_H 139590837bSKentaro Takeda #define _SECURITY_TOMOYO_COMMON_H 149590837bSKentaro Takeda 159590837bSKentaro Takeda #include <linux/ctype.h> 169590837bSKentaro Takeda #include <linux/string.h> 179590837bSKentaro Takeda #include <linux/mm.h> 189590837bSKentaro Takeda #include <linux/file.h> 199590837bSKentaro Takeda #include <linux/kmod.h> 209590837bSKentaro Takeda #include <linux/fs.h> 219590837bSKentaro Takeda #include <linux/sched.h> 229590837bSKentaro Takeda #include <linux/namei.h> 239590837bSKentaro Takeda #include <linux/mount.h> 249590837bSKentaro Takeda #include <linux/list.h> 259590837bSKentaro Takeda 269590837bSKentaro Takeda struct dentry; 279590837bSKentaro Takeda struct vfsmount; 289590837bSKentaro Takeda 299590837bSKentaro Takeda /* Temporary buffer for holding pathnames. */ 309590837bSKentaro Takeda struct tomoyo_page_buffer { 319590837bSKentaro Takeda char buffer[4096]; 329590837bSKentaro Takeda }; 339590837bSKentaro Takeda 349590837bSKentaro Takeda /* Structure for holding a token. */ 359590837bSKentaro Takeda struct tomoyo_path_info { 369590837bSKentaro Takeda const char *name; 379590837bSKentaro Takeda u32 hash; /* = full_name_hash(name, strlen(name)) */ 389590837bSKentaro Takeda u16 total_len; /* = strlen(name) */ 399590837bSKentaro Takeda u16 const_len; /* = tomoyo_const_part_length(name) */ 409590837bSKentaro Takeda bool is_dir; /* = tomoyo_strendswith(name, "/") */ 419590837bSKentaro Takeda bool is_patterned; /* = tomoyo_path_contains_pattern(name) */ 429590837bSKentaro Takeda u16 depth; /* = tomoyo_path_depth(name) */ 439590837bSKentaro Takeda }; 449590837bSKentaro Takeda 459590837bSKentaro Takeda /* 469590837bSKentaro Takeda * This is the max length of a token. 479590837bSKentaro Takeda * 489590837bSKentaro Takeda * A token consists of only ASCII printable characters. 499590837bSKentaro Takeda * Non printable characters in a token is represented in \ooo style 509590837bSKentaro Takeda * octal string. Thus, \ itself is represented as \\. 519590837bSKentaro Takeda */ 529590837bSKentaro Takeda #define TOMOYO_MAX_PATHNAME_LEN 4000 539590837bSKentaro Takeda 549590837bSKentaro Takeda /* Structure for holding requested pathname. */ 559590837bSKentaro Takeda struct tomoyo_path_info_with_data { 569590837bSKentaro Takeda /* Keep "head" first, for this pointer is passed to tomoyo_free(). */ 579590837bSKentaro Takeda struct tomoyo_path_info head; 58a106cbfdSTetsuo Handa char barrier1[16]; /* Safeguard for overrun. */ 599590837bSKentaro Takeda char body[TOMOYO_MAX_PATHNAME_LEN]; 609590837bSKentaro Takeda char barrier2[16]; /* Safeguard for overrun. */ 619590837bSKentaro Takeda }; 629590837bSKentaro Takeda 639590837bSKentaro Takeda /* 649590837bSKentaro Takeda * Common header for holding ACL entries. 659590837bSKentaro Takeda * 669590837bSKentaro Takeda * Packing "struct tomoyo_acl_info" allows 679590837bSKentaro Takeda * "struct tomoyo_single_path_acl_record" to embed "u16" and 689590837bSKentaro Takeda * "struct tomoyo_double_path_acl_record" to embed "u8" 699590837bSKentaro Takeda * without enlarging their structure size. 709590837bSKentaro Takeda */ 719590837bSKentaro Takeda struct tomoyo_acl_info { 729590837bSKentaro Takeda struct list_head list; 739590837bSKentaro Takeda /* 749590837bSKentaro Takeda * Type of this ACL entry. 759590837bSKentaro Takeda * 769590837bSKentaro Takeda * MSB is is_deleted flag. 779590837bSKentaro Takeda */ 789590837bSKentaro Takeda u8 type; 799590837bSKentaro Takeda } __packed; 809590837bSKentaro Takeda 819590837bSKentaro Takeda /* This ACL entry is deleted. */ 829590837bSKentaro Takeda #define TOMOYO_ACL_DELETED 0x80 839590837bSKentaro Takeda 849590837bSKentaro Takeda /* Structure for domain information. */ 859590837bSKentaro Takeda struct tomoyo_domain_info { 869590837bSKentaro Takeda struct list_head list; 879590837bSKentaro Takeda struct list_head acl_info_list; 889590837bSKentaro Takeda /* Name of this domain. Never NULL. */ 899590837bSKentaro Takeda const struct tomoyo_path_info *domainname; 909590837bSKentaro Takeda u8 profile; /* Profile number to use. */ 91a0558fc3STetsuo Handa bool is_deleted; /* Delete flag. */ 929590837bSKentaro Takeda bool quota_warned; /* Quota warnning flag. */ 939590837bSKentaro Takeda /* DOMAIN_FLAGS_*. Use tomoyo_set_domain_flag() to modify. */ 949590837bSKentaro Takeda u8 flags; 959590837bSKentaro Takeda }; 969590837bSKentaro Takeda 979590837bSKentaro Takeda /* Profile number is an integer between 0 and 255. */ 989590837bSKentaro Takeda #define TOMOYO_MAX_PROFILES 256 999590837bSKentaro Takeda 1009590837bSKentaro Takeda /* Ignore "allow_read" directive in exception policy. */ 1019590837bSKentaro Takeda #define TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ 1 1029590837bSKentaro Takeda /* 1039590837bSKentaro Takeda * This domain was unable to create a new domain at tomoyo_find_next_domain() 1049590837bSKentaro Takeda * because the name of the domain to be created was too long or 1059590837bSKentaro Takeda * it could not allocate memory. 1069590837bSKentaro Takeda * More than one process continued execve() without domain transition. 1079590837bSKentaro Takeda */ 1089590837bSKentaro Takeda #define TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED 2 1099590837bSKentaro Takeda 1109590837bSKentaro Takeda /* 1119590837bSKentaro Takeda * Structure for "allow_read/write", "allow_execute", "allow_read", 1129590837bSKentaro Takeda * "allow_write", "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir", 1139590837bSKentaro Takeda * "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar", 1149590837bSKentaro Takeda * "allow_truncate", "allow_symlink" and "allow_rewrite" directive. 1159590837bSKentaro Takeda */ 1169590837bSKentaro Takeda struct tomoyo_single_path_acl_record { 1179590837bSKentaro Takeda struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_SINGLE_PATH_ACL */ 1189590837bSKentaro Takeda u16 perm; 1199590837bSKentaro Takeda /* Pointer to single pathname. */ 1209590837bSKentaro Takeda const struct tomoyo_path_info *filename; 1219590837bSKentaro Takeda }; 1229590837bSKentaro Takeda 1239590837bSKentaro Takeda /* Structure for "allow_rename" and "allow_link" directive. */ 1249590837bSKentaro Takeda struct tomoyo_double_path_acl_record { 1259590837bSKentaro Takeda struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_DOUBLE_PATH_ACL */ 1269590837bSKentaro Takeda u8 perm; 1279590837bSKentaro Takeda /* Pointer to single pathname. */ 1289590837bSKentaro Takeda const struct tomoyo_path_info *filename1; 1299590837bSKentaro Takeda /* Pointer to single pathname. */ 1309590837bSKentaro Takeda const struct tomoyo_path_info *filename2; 1319590837bSKentaro Takeda }; 1329590837bSKentaro Takeda 1339590837bSKentaro Takeda /* Keywords for ACLs. */ 1349590837bSKentaro Takeda #define TOMOYO_KEYWORD_ALIAS "alias " 1359590837bSKentaro Takeda #define TOMOYO_KEYWORD_ALLOW_READ "allow_read " 1369590837bSKentaro Takeda #define TOMOYO_KEYWORD_DELETE "delete " 1379590837bSKentaro Takeda #define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite " 1389590837bSKentaro Takeda #define TOMOYO_KEYWORD_FILE_PATTERN "file_pattern " 1399590837bSKentaro Takeda #define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain " 1409590837bSKentaro Takeda #define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " 1419590837bSKentaro Takeda #define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " 1429590837bSKentaro Takeda #define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " 1439590837bSKentaro Takeda #define TOMOYO_KEYWORD_SELECT "select " 1449590837bSKentaro Takeda #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " 1459590837bSKentaro Takeda #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" 1469590837bSKentaro Takeda /* A domain definition starts with <kernel>. */ 1479590837bSKentaro Takeda #define TOMOYO_ROOT_NAME "<kernel>" 1489590837bSKentaro Takeda #define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) 1499590837bSKentaro Takeda 1509590837bSKentaro Takeda /* Index numbers for Access Controls. */ 1519590837bSKentaro Takeda #define TOMOYO_MAC_FOR_FILE 0 /* domain_policy.conf */ 1529590837bSKentaro Takeda #define TOMOYO_MAX_ACCEPT_ENTRY 1 1539590837bSKentaro Takeda #define TOMOYO_VERBOSE 2 1549590837bSKentaro Takeda #define TOMOYO_MAX_CONTROL_INDEX 3 1559590837bSKentaro Takeda 1569590837bSKentaro Takeda /* Structure for reading/writing policy via securityfs interfaces. */ 1579590837bSKentaro Takeda struct tomoyo_io_buffer { 1589590837bSKentaro Takeda int (*read) (struct tomoyo_io_buffer *); 1599590837bSKentaro Takeda int (*write) (struct tomoyo_io_buffer *); 1609590837bSKentaro Takeda /* Exclusive lock for this structure. */ 1619590837bSKentaro Takeda struct mutex io_sem; 1629590837bSKentaro Takeda /* The position currently reading from. */ 1639590837bSKentaro Takeda struct list_head *read_var1; 1649590837bSKentaro Takeda /* Extra variables for reading. */ 1659590837bSKentaro Takeda struct list_head *read_var2; 1669590837bSKentaro Takeda /* The position currently writing to. */ 1679590837bSKentaro Takeda struct tomoyo_domain_info *write_var1; 1689590837bSKentaro Takeda /* The step for reading. */ 1699590837bSKentaro Takeda int read_step; 1709590837bSKentaro Takeda /* Buffer for reading. */ 1719590837bSKentaro Takeda char *read_buf; 1729590837bSKentaro Takeda /* EOF flag for reading. */ 1739590837bSKentaro Takeda bool read_eof; 1749590837bSKentaro Takeda /* Read domain ACL of specified PID? */ 1759590837bSKentaro Takeda bool read_single_domain; 1769590837bSKentaro Takeda /* Extra variable for reading. */ 1779590837bSKentaro Takeda u8 read_bit; 1789590837bSKentaro Takeda /* Bytes available for reading. */ 1799590837bSKentaro Takeda int read_avail; 1809590837bSKentaro Takeda /* Size of read buffer. */ 1819590837bSKentaro Takeda int readbuf_size; 1829590837bSKentaro Takeda /* Buffer for writing. */ 1839590837bSKentaro Takeda char *write_buf; 1849590837bSKentaro Takeda /* Bytes available for writing. */ 1859590837bSKentaro Takeda int write_avail; 1869590837bSKentaro Takeda /* Size of write buffer. */ 1879590837bSKentaro Takeda int writebuf_size; 1889590837bSKentaro Takeda }; 1899590837bSKentaro Takeda 1909590837bSKentaro Takeda /* Check whether the domain has too many ACL entries to hold. */ 1919590837bSKentaro Takeda bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); 1929590837bSKentaro Takeda /* Transactional sprintf() for policy dump. */ 1939590837bSKentaro Takeda bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) 1949590837bSKentaro Takeda __attribute__ ((format(printf, 2, 3))); 1959590837bSKentaro Takeda /* Check whether the domainname is correct. */ 1969590837bSKentaro Takeda bool tomoyo_is_correct_domain(const unsigned char *domainname, 1979590837bSKentaro Takeda const char *function); 1989590837bSKentaro Takeda /* Check whether the token is correct. */ 1999590837bSKentaro Takeda bool tomoyo_is_correct_path(const char *filename, const s8 start_type, 2009590837bSKentaro Takeda const s8 pattern_type, const s8 end_type, 2019590837bSKentaro Takeda const char *function); 2029590837bSKentaro Takeda /* Check whether the token can be a domainname. */ 2039590837bSKentaro Takeda bool tomoyo_is_domain_def(const unsigned char *buffer); 2049590837bSKentaro Takeda /* Check whether the given filename matches the given pattern. */ 2059590837bSKentaro Takeda bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, 2069590837bSKentaro Takeda const struct tomoyo_path_info *pattern); 2079590837bSKentaro Takeda /* Read "alias" entry in exception policy. */ 2089590837bSKentaro Takeda bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head); 2099590837bSKentaro Takeda /* 2109590837bSKentaro Takeda * Read "initialize_domain" and "no_initialize_domain" entry 2119590837bSKentaro Takeda * in exception policy. 2129590837bSKentaro Takeda */ 2139590837bSKentaro Takeda bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head); 2149590837bSKentaro Takeda /* Read "keep_domain" and "no_keep_domain" entry in exception policy. */ 2159590837bSKentaro Takeda bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head); 2169590837bSKentaro Takeda /* Read "file_pattern" entry in exception policy. */ 2179590837bSKentaro Takeda bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head); 2189590837bSKentaro Takeda /* Read "allow_read" entry in exception policy. */ 2199590837bSKentaro Takeda bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head); 2209590837bSKentaro Takeda /* Read "deny_rewrite" entry in exception policy. */ 2219590837bSKentaro Takeda bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head); 2229590837bSKentaro Takeda /* Write domain policy violation warning message to console? */ 2239590837bSKentaro Takeda bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); 2249590837bSKentaro Takeda /* Convert double path operation to operation name. */ 2259590837bSKentaro Takeda const char *tomoyo_dp2keyword(const u8 operation); 2269590837bSKentaro Takeda /* Get the last component of the given domainname. */ 2279590837bSKentaro Takeda const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); 2289590837bSKentaro Takeda /* Get warning message. */ 2299590837bSKentaro Takeda const char *tomoyo_get_msg(const bool is_enforce); 2309590837bSKentaro Takeda /* Convert single path operation to operation name. */ 2319590837bSKentaro Takeda const char *tomoyo_sp2keyword(const u8 operation); 2329590837bSKentaro Takeda /* Delete a domain. */ 2339590837bSKentaro Takeda int tomoyo_delete_domain(char *data); 2349590837bSKentaro Takeda /* Create "alias" entry in exception policy. */ 2359590837bSKentaro Takeda int tomoyo_write_alias_policy(char *data, const bool is_delete); 2369590837bSKentaro Takeda /* 2379590837bSKentaro Takeda * Create "initialize_domain" and "no_initialize_domain" entry 2389590837bSKentaro Takeda * in exception policy. 2399590837bSKentaro Takeda */ 2409590837bSKentaro Takeda int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, 2419590837bSKentaro Takeda const bool is_delete); 2429590837bSKentaro Takeda /* Create "keep_domain" and "no_keep_domain" entry in exception policy. */ 2439590837bSKentaro Takeda int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, 2449590837bSKentaro Takeda const bool is_delete); 2459590837bSKentaro Takeda /* 2469590837bSKentaro Takeda * Create "allow_read/write", "allow_execute", "allow_read", "allow_write", 2479590837bSKentaro Takeda * "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir", 2489590837bSKentaro Takeda * "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar", 2499590837bSKentaro Takeda * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_rename" and 2509590837bSKentaro Takeda * "allow_link" entry in domain policy. 2519590837bSKentaro Takeda */ 2529590837bSKentaro Takeda int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, 2539590837bSKentaro Takeda const bool is_delete); 2549590837bSKentaro Takeda /* Create "allow_read" entry in exception policy. */ 2559590837bSKentaro Takeda int tomoyo_write_globally_readable_policy(char *data, const bool is_delete); 2569590837bSKentaro Takeda /* Create "deny_rewrite" entry in exception policy. */ 2579590837bSKentaro Takeda int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); 2589590837bSKentaro Takeda /* Create "file_pattern" entry in exception policy. */ 2599590837bSKentaro Takeda int tomoyo_write_pattern_policy(char *data, const bool is_delete); 2609590837bSKentaro Takeda /* Find a domain by the given name. */ 2619590837bSKentaro Takeda struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); 2629590837bSKentaro Takeda /* Find or create a domain by the given name. */ 2639590837bSKentaro Takeda struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 2649590837bSKentaro Takeda domainname, 2659590837bSKentaro Takeda const u8 profile); 2669590837bSKentaro Takeda /* Check mode for specified functionality. */ 2679590837bSKentaro Takeda unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, 2689590837bSKentaro Takeda const u8 index); 2699590837bSKentaro Takeda /* Allocate memory for structures. */ 2709590837bSKentaro Takeda void *tomoyo_alloc_acl_element(const u8 acl_type); 2719590837bSKentaro Takeda /* Fill in "struct tomoyo_path_info" members. */ 2729590837bSKentaro Takeda void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); 2739590837bSKentaro Takeda /* Run policy loader when /sbin/init starts. */ 2749590837bSKentaro Takeda void tomoyo_load_policy(const char *filename); 2759590837bSKentaro Takeda /* Change "struct tomoyo_domain_info"->flags. */ 2769590837bSKentaro Takeda void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain, 2779590837bSKentaro Takeda const bool is_delete, const u8 flags); 2789590837bSKentaro Takeda 2799590837bSKentaro Takeda /* strcmp() for "struct tomoyo_path_info" structure. */ 2809590837bSKentaro Takeda static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, 2819590837bSKentaro Takeda const struct tomoyo_path_info *b) 2829590837bSKentaro Takeda { 2839590837bSKentaro Takeda return a->hash != b->hash || strcmp(a->name, b->name); 2849590837bSKentaro Takeda } 2859590837bSKentaro Takeda 2869590837bSKentaro Takeda /* Get type of an ACL entry. */ 2879590837bSKentaro Takeda static inline u8 tomoyo_acl_type1(struct tomoyo_acl_info *ptr) 2889590837bSKentaro Takeda { 2899590837bSKentaro Takeda return ptr->type & ~TOMOYO_ACL_DELETED; 2909590837bSKentaro Takeda } 2919590837bSKentaro Takeda 2929590837bSKentaro Takeda /* Get type of an ACL entry. */ 2939590837bSKentaro Takeda static inline u8 tomoyo_acl_type2(struct tomoyo_acl_info *ptr) 2949590837bSKentaro Takeda { 2959590837bSKentaro Takeda return ptr->type; 2969590837bSKentaro Takeda } 2979590837bSKentaro Takeda 2989590837bSKentaro Takeda /** 2999590837bSKentaro Takeda * tomoyo_is_valid - Check whether the character is a valid char. 3009590837bSKentaro Takeda * 3019590837bSKentaro Takeda * @c: The character to check. 3029590837bSKentaro Takeda * 3039590837bSKentaro Takeda * Returns true if @c is a valid character, false otherwise. 3049590837bSKentaro Takeda */ 3059590837bSKentaro Takeda static inline bool tomoyo_is_valid(const unsigned char c) 3069590837bSKentaro Takeda { 3079590837bSKentaro Takeda return c > ' ' && c < 127; 3089590837bSKentaro Takeda } 3099590837bSKentaro Takeda 3109590837bSKentaro Takeda /** 3119590837bSKentaro Takeda * tomoyo_is_invalid - Check whether the character is an invalid char. 3129590837bSKentaro Takeda * 3139590837bSKentaro Takeda * @c: The character to check. 3149590837bSKentaro Takeda * 3159590837bSKentaro Takeda * Returns true if @c is an invalid character, false otherwise. 3169590837bSKentaro Takeda */ 3179590837bSKentaro Takeda static inline bool tomoyo_is_invalid(const unsigned char c) 3189590837bSKentaro Takeda { 3199590837bSKentaro Takeda return c && (c <= ' ' || c >= 127); 3209590837bSKentaro Takeda } 3219590837bSKentaro Takeda 3229590837bSKentaro Takeda /* The list for "struct tomoyo_domain_info". */ 3239590837bSKentaro Takeda extern struct list_head tomoyo_domain_list; 3249590837bSKentaro Takeda extern struct rw_semaphore tomoyo_domain_list_lock; 3259590837bSKentaro Takeda 3269590837bSKentaro Takeda /* Lock for domain->acl_info_list. */ 3279590837bSKentaro Takeda extern struct rw_semaphore tomoyo_domain_acl_info_list_lock; 3289590837bSKentaro Takeda 3299590837bSKentaro Takeda /* Has /sbin/init started? */ 3309590837bSKentaro Takeda extern bool tomoyo_policy_loaded; 3319590837bSKentaro Takeda 3329590837bSKentaro Takeda /* The kernel's domain. */ 3339590837bSKentaro Takeda extern struct tomoyo_domain_info tomoyo_kernel_domain; 3349590837bSKentaro Takeda 3359590837bSKentaro Takeda /** 3369590837bSKentaro Takeda * list_for_each_cookie - iterate over a list with cookie. 3379590837bSKentaro Takeda * @pos: the &struct list_head to use as a loop cursor. 3389590837bSKentaro Takeda * @cookie: the &struct list_head to use as a cookie. 3399590837bSKentaro Takeda * @head: the head for your list. 3409590837bSKentaro Takeda * 3419590837bSKentaro Takeda * Same with list_for_each() except that this primitive uses @cookie 3429590837bSKentaro Takeda * so that we can continue iteration. 3439590837bSKentaro Takeda * @cookie must be NULL when iteration starts, and @cookie will become 3449590837bSKentaro Takeda * NULL when iteration finishes. 3459590837bSKentaro Takeda */ 3469590837bSKentaro Takeda #define list_for_each_cookie(pos, cookie, head) \ 3479590837bSKentaro Takeda for (({ if (!cookie) \ 3489590837bSKentaro Takeda cookie = head; }), \ 3499590837bSKentaro Takeda pos = (cookie)->next; \ 3509590837bSKentaro Takeda prefetch(pos->next), pos != (head) || ((cookie) = NULL); \ 3519590837bSKentaro Takeda (cookie) = pos, pos = pos->next) 3529590837bSKentaro Takeda 3539590837bSKentaro Takeda #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ 354