Commit b22b8b9fd90eecfb7133e56b4e113595f09f4492
Committed by
James Morris
1 parent
2c47ab9353
Exists in
master
and in
6 other branches
TOMOYO: Rename meminfo to stat and show more statistics.
Show statistics such as last policy update time and last policy violation time in addition to memory usage. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <jmorris@namei.org>
Showing 6 changed files with 206 additions and 143 deletions Side-by-side Diff
security/tomoyo/audit.c
... | ... | @@ -10,47 +10,6 @@ |
10 | 10 | #include <linux/slab.h> |
11 | 11 | |
12 | 12 | /** |
13 | - * tomoyo_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss. | |
14 | - * | |
15 | - * @time: Seconds since 1970/01/01 00:00:00. | |
16 | - * @stamp: Pointer to "struct tomoyo_time". | |
17 | - * | |
18 | - * Returns nothing. | |
19 | - * | |
20 | - * This function does not handle Y2038 problem. | |
21 | - */ | |
22 | -static void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp) | |
23 | -{ | |
24 | - static const u16 tomoyo_eom[2][12] = { | |
25 | - { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, | |
26 | - { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } | |
27 | - }; | |
28 | - u16 y; | |
29 | - u8 m; | |
30 | - bool r; | |
31 | - stamp->sec = time % 60; | |
32 | - time /= 60; | |
33 | - stamp->min = time % 60; | |
34 | - time /= 60; | |
35 | - stamp->hour = time % 24; | |
36 | - time /= 24; | |
37 | - for (y = 1970; ; y++) { | |
38 | - const unsigned short days = (y & 3) ? 365 : 366; | |
39 | - if (time < days) | |
40 | - break; | |
41 | - time -= days; | |
42 | - } | |
43 | - r = (y & 3) == 0; | |
44 | - for (m = 0; m < 11 && time >= tomoyo_eom[r][m]; m++) | |
45 | - ; | |
46 | - if (m) | |
47 | - time -= tomoyo_eom[r][m - 1]; | |
48 | - stamp->year = y; | |
49 | - stamp->month = ++m; | |
50 | - stamp->day = ++time; | |
51 | -} | |
52 | - | |
53 | -/** | |
54 | 13 | * tomoyo_print_header - Get header line of audit log. |
55 | 14 | * |
56 | 15 | * @r: Pointer to "struct tomoyo_request_info". |
security/tomoyo/common.c
... | ... | @@ -1584,8 +1584,9 @@ |
1584 | 1584 | return; |
1585 | 1585 | snprintf(buffer, len - 1, "%s", cp); |
1586 | 1586 | tomoyo_normalize_line(buffer); |
1587 | - tomoyo_write_domain2(domain->ns, &domain->acl_info_list, buffer, | |
1588 | - false); | |
1587 | + if (!tomoyo_write_domain2(domain->ns, &domain->acl_info_list, buffer, | |
1588 | + false)) | |
1589 | + tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES); | |
1589 | 1590 | kfree(buffer); |
1590 | 1591 | } |
1591 | 1592 | |
... | ... | @@ -1618,6 +1619,8 @@ |
1618 | 1619 | /* Nothing more to do if granted. */ |
1619 | 1620 | if (r->granted) |
1620 | 1621 | return 0; |
1622 | + if (r->mode) | |
1623 | + tomoyo_update_stat(r->mode); | |
1621 | 1624 | switch (r->mode) { |
1622 | 1625 | case TOMOYO_CONFIG_ENFORCING: |
1623 | 1626 | error = -EPERM; |
1624 | 1627 | |
... | ... | @@ -1857,7 +1860,105 @@ |
1857 | 1860 | } |
1858 | 1861 | } |
1859 | 1862 | |
1863 | +/* String table for /sys/kernel/security/tomoyo/stat interface. */ | |
1864 | +static const char * const tomoyo_policy_headers[TOMOYO_MAX_POLICY_STAT] = { | |
1865 | + [TOMOYO_STAT_POLICY_UPDATES] = "update:", | |
1866 | + [TOMOYO_STAT_POLICY_LEARNING] = "violation in learning mode:", | |
1867 | + [TOMOYO_STAT_POLICY_PERMISSIVE] = "violation in permissive mode:", | |
1868 | + [TOMOYO_STAT_POLICY_ENFORCING] = "violation in enforcing mode:", | |
1869 | +}; | |
1870 | + | |
1871 | +/* String table for /sys/kernel/security/tomoyo/stat interface. */ | |
1872 | +static const char * const tomoyo_memory_headers[TOMOYO_MAX_MEMORY_STAT] = { | |
1873 | + [TOMOYO_MEMORY_POLICY] = "policy:", | |
1874 | + [TOMOYO_MEMORY_AUDIT] = "audit log:", | |
1875 | + [TOMOYO_MEMORY_QUERY] = "query message:", | |
1876 | +}; | |
1877 | + | |
1878 | +/* Timestamp counter for last updated. */ | |
1879 | +static unsigned int tomoyo_stat_updated[TOMOYO_MAX_POLICY_STAT]; | |
1880 | +/* Counter for number of updates. */ | |
1881 | +static unsigned int tomoyo_stat_modified[TOMOYO_MAX_POLICY_STAT]; | |
1882 | + | |
1860 | 1883 | /** |
1884 | + * tomoyo_update_stat - Update statistic counters. | |
1885 | + * | |
1886 | + * @index: Index for policy type. | |
1887 | + * | |
1888 | + * Returns nothing. | |
1889 | + */ | |
1890 | +void tomoyo_update_stat(const u8 index) | |
1891 | +{ | |
1892 | + struct timeval tv; | |
1893 | + do_gettimeofday(&tv); | |
1894 | + /* | |
1895 | + * I don't use atomic operations because race condition is not fatal. | |
1896 | + */ | |
1897 | + tomoyo_stat_updated[index]++; | |
1898 | + tomoyo_stat_modified[index] = tv.tv_sec; | |
1899 | +} | |
1900 | + | |
1901 | +/** | |
1902 | + * tomoyo_read_stat - Read statistic data. | |
1903 | + * | |
1904 | + * @head: Pointer to "struct tomoyo_io_buffer". | |
1905 | + * | |
1906 | + * Returns nothing. | |
1907 | + */ | |
1908 | +static void tomoyo_read_stat(struct tomoyo_io_buffer *head) | |
1909 | +{ | |
1910 | + u8 i; | |
1911 | + unsigned int total = 0; | |
1912 | + if (head->r.eof) | |
1913 | + return; | |
1914 | + for (i = 0; i < TOMOYO_MAX_POLICY_STAT; i++) { | |
1915 | + tomoyo_io_printf(head, "Policy %-30s %10u", | |
1916 | + tomoyo_policy_headers[i], | |
1917 | + tomoyo_stat_updated[i]); | |
1918 | + if (tomoyo_stat_modified[i]) { | |
1919 | + struct tomoyo_time stamp; | |
1920 | + tomoyo_convert_time(tomoyo_stat_modified[i], &stamp); | |
1921 | + tomoyo_io_printf(head, " (Last: %04u/%02u/%02u " | |
1922 | + "%02u:%02u:%02u)", | |
1923 | + stamp.year, stamp.month, stamp.day, | |
1924 | + stamp.hour, stamp.min, stamp.sec); | |
1925 | + } | |
1926 | + tomoyo_set_lf(head); | |
1927 | + } | |
1928 | + for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++) { | |
1929 | + unsigned int used = tomoyo_memory_used[i]; | |
1930 | + total += used; | |
1931 | + tomoyo_io_printf(head, "Memory used by %-22s %10u", | |
1932 | + tomoyo_memory_headers[i], used); | |
1933 | + used = tomoyo_memory_quota[i]; | |
1934 | + if (used) | |
1935 | + tomoyo_io_printf(head, " (Quota: %10u)", used); | |
1936 | + tomoyo_set_lf(head); | |
1937 | + } | |
1938 | + tomoyo_io_printf(head, "Total memory used: %10u\n", | |
1939 | + total); | |
1940 | + head->r.eof = true; | |
1941 | +} | |
1942 | + | |
1943 | +/** | |
1944 | + * tomoyo_write_stat - Set memory quota. | |
1945 | + * | |
1946 | + * @head: Pointer to "struct tomoyo_io_buffer". | |
1947 | + * | |
1948 | + * Returns 0. | |
1949 | + */ | |
1950 | +static int tomoyo_write_stat(struct tomoyo_io_buffer *head) | |
1951 | +{ | |
1952 | + char *data = head->write_buf; | |
1953 | + u8 i; | |
1954 | + if (tomoyo_str_starts(&data, "Memory used by ")) | |
1955 | + for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++) | |
1956 | + if (tomoyo_str_starts(&data, tomoyo_memory_headers[i])) | |
1957 | + sscanf(data, "%u", &tomoyo_memory_quota[i]); | |
1958 | + return 0; | |
1959 | +} | |
1960 | + | |
1961 | +/** | |
1861 | 1962 | * tomoyo_open_control - open() for /sys/kernel/security/tomoyo/ interface. |
1862 | 1963 | * |
1863 | 1964 | * @type: Type of interface. |
... | ... | @@ -1908,11 +2009,11 @@ |
1908 | 2009 | head->read = tomoyo_read_version; |
1909 | 2010 | head->readbuf_size = 128; |
1910 | 2011 | break; |
1911 | - case TOMOYO_MEMINFO: | |
1912 | - /* /sys/kernel/security/tomoyo/meminfo */ | |
1913 | - head->write = tomoyo_write_memory_quota; | |
1914 | - head->read = tomoyo_read_memory_counter; | |
1915 | - head->readbuf_size = 512; | |
2012 | + case TOMOYO_STAT: | |
2013 | + /* /sys/kernel/security/tomoyo/stat */ | |
2014 | + head->write = tomoyo_write_stat; | |
2015 | + head->read = tomoyo_read_stat; | |
2016 | + head->readbuf_size = 1024; | |
1916 | 2017 | break; |
1917 | 2018 | case TOMOYO_PROFILE: |
1918 | 2019 | /* /sys/kernel/security/tomoyo/profile */ |
... | ... | @@ -2186,6 +2287,20 @@ |
2186 | 2287 | case -EPERM: |
2187 | 2288 | error = -EPERM; |
2188 | 2289 | goto out; |
2290 | + case 0: | |
2291 | + switch (head->type) { | |
2292 | + case TOMOYO_DOMAINPOLICY: | |
2293 | + case TOMOYO_EXCEPTIONPOLICY: | |
2294 | + case TOMOYO_DOMAIN_STATUS: | |
2295 | + case TOMOYO_STAT: | |
2296 | + case TOMOYO_PROFILE: | |
2297 | + case TOMOYO_MANAGER: | |
2298 | + tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES); | |
2299 | + break; | |
2300 | + default: | |
2301 | + break; | |
2302 | + } | |
2303 | + break; | |
2189 | 2304 | } |
2190 | 2305 | } |
2191 | 2306 | out: |
security/tomoyo/common.h
... | ... | @@ -133,6 +133,7 @@ |
133 | 133 | TOMOYO_MAX_PATH_OPERATION |
134 | 134 | }; |
135 | 135 | |
136 | +/* Index numbers for /sys/kernel/security/tomoyo/stat interface. */ | |
136 | 137 | enum tomoyo_memory_stat_type { |
137 | 138 | TOMOYO_MEMORY_POLICY, |
138 | 139 | TOMOYO_MEMORY_AUDIT, |
... | ... | @@ -173,7 +174,7 @@ |
173 | 174 | TOMOYO_EXCEPTIONPOLICY, |
174 | 175 | TOMOYO_DOMAIN_STATUS, |
175 | 176 | TOMOYO_PROCESS_STATUS, |
176 | - TOMOYO_MEMINFO, | |
177 | + TOMOYO_STAT, | |
177 | 178 | TOMOYO_SELFDOMAIN, |
178 | 179 | TOMOYO_AUDIT, |
179 | 180 | TOMOYO_VERSION, |
... | ... | @@ -237,6 +238,16 @@ |
237 | 238 | */ |
238 | 239 | #define TOMOYO_RETRY_REQUEST 1 |
239 | 240 | |
241 | +/* Index numbers for /sys/kernel/security/tomoyo/stat interface. */ | |
242 | +enum tomoyo_policy_stat_type { | |
243 | + /* Do not change this order. */ | |
244 | + TOMOYO_STAT_POLICY_UPDATES, | |
245 | + TOMOYO_STAT_POLICY_LEARNING, /* == TOMOYO_CONFIG_LEARNING */ | |
246 | + TOMOYO_STAT_POLICY_PERMISSIVE, /* == TOMOYO_CONFIG_PERMISSIVE */ | |
247 | + TOMOYO_STAT_POLICY_ENFORCING, /* == TOMOYO_CONFIG_ENFORCING */ | |
248 | + TOMOYO_MAX_POLICY_STAT | |
249 | +}; | |
250 | + | |
240 | 251 | /* Index numbers for profile's PREFERENCE values. */ |
241 | 252 | enum tomoyo_pref_index { |
242 | 253 | TOMOYO_PREF_MAX_AUDIT_LOG, |
... | ... | @@ -648,8 +659,8 @@ |
648 | 659 | bool tomoyo_memory_ok(void *ptr); |
649 | 660 | void *tomoyo_commit_ok(void *data, const unsigned int size); |
650 | 661 | const struct tomoyo_path_info *tomoyo_get_name(const char *name); |
651 | -void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); | |
652 | -int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); | |
662 | +void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp); | |
663 | +void tomoyo_update_stat(const u8 index); | |
653 | 664 | void __init tomoyo_mm_init(void); |
654 | 665 | int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, |
655 | 666 | const struct tomoyo_path_info *filename); |
security/tomoyo/memory.c
... | ... | @@ -29,16 +29,13 @@ |
29 | 29 | panic("MAC Initialization failed.\n"); |
30 | 30 | } |
31 | 31 | |
32 | +/* Lock for protecting tomoyo_memory_used. */ | |
33 | +static DEFINE_SPINLOCK(tomoyo_policy_memory_lock); | |
32 | 34 | /* Memoy currently used by policy/audit log/query. */ |
33 | 35 | unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; |
34 | 36 | /* Memory quota for "policy"/"audit log"/"query". */ |
35 | 37 | unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT]; |
36 | 38 | |
37 | -/* Memory allocated for policy. */ | |
38 | -static atomic_t tomoyo_policy_memory_size; | |
39 | -/* Quota for holding policy. */ | |
40 | -static unsigned int tomoyo_quota_for_policy; | |
41 | - | |
42 | 39 | /** |
43 | 40 | * tomoyo_memory_ok - Check memory quota. |
44 | 41 | * |
45 | 42 | |
... | ... | @@ -50,15 +47,20 @@ |
50 | 47 | */ |
51 | 48 | bool tomoyo_memory_ok(void *ptr) |
52 | 49 | { |
53 | - size_t s = ptr ? ksize(ptr) : 0; | |
54 | - atomic_add(s, &tomoyo_policy_memory_size); | |
55 | - if (ptr && (!tomoyo_quota_for_policy || | |
56 | - atomic_read(&tomoyo_policy_memory_size) | |
57 | - <= tomoyo_quota_for_policy)) { | |
58 | - memset(ptr, 0, s); | |
59 | - return true; | |
50 | + if (ptr) { | |
51 | + const size_t s = ksize(ptr); | |
52 | + bool result; | |
53 | + spin_lock(&tomoyo_policy_memory_lock); | |
54 | + tomoyo_memory_used[TOMOYO_MEMORY_POLICY] += s; | |
55 | + result = !tomoyo_memory_quota[TOMOYO_MEMORY_POLICY] || | |
56 | + tomoyo_memory_used[TOMOYO_MEMORY_POLICY] <= | |
57 | + tomoyo_memory_quota[TOMOYO_MEMORY_POLICY]; | |
58 | + if (!result) | |
59 | + tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s; | |
60 | + spin_unlock(&tomoyo_policy_memory_lock); | |
61 | + if (result) | |
62 | + return true; | |
60 | 63 | } |
61 | - atomic_sub(s, &tomoyo_policy_memory_size); | |
62 | 64 | tomoyo_warn_oom(__func__); |
63 | 65 | return false; |
64 | 66 | } |
... | ... | @@ -91,7 +93,10 @@ |
91 | 93 | */ |
92 | 94 | void tomoyo_memory_free(void *ptr) |
93 | 95 | { |
94 | - atomic_sub(ksize(ptr), &tomoyo_policy_memory_size); | |
96 | + size_t s = ksize(ptr); | |
97 | + spin_lock(&tomoyo_policy_memory_lock); | |
98 | + tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s; | |
99 | + spin_unlock(&tomoyo_policy_memory_lock); | |
95 | 100 | kfree(ptr); |
96 | 101 | } |
97 | 102 | |
... | ... | @@ -162,7 +167,6 @@ |
162 | 167 | struct tomoyo_name *ptr; |
163 | 168 | unsigned int hash; |
164 | 169 | int len; |
165 | - int allocated_len; | |
166 | 170 | struct list_head *head; |
167 | 171 | |
168 | 172 | if (!name) |
169 | 173 | |
170 | 174 | |
... | ... | @@ -179,22 +183,17 @@ |
179 | 183 | goto out; |
180 | 184 | } |
181 | 185 | ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); |
182 | - allocated_len = ptr ? ksize(ptr) : 0; | |
183 | - if (!ptr || (tomoyo_quota_for_policy && | |
184 | - atomic_read(&tomoyo_policy_memory_size) + allocated_len | |
185 | - > tomoyo_quota_for_policy)) { | |
186 | + if (tomoyo_memory_ok(ptr)) { | |
187 | + ptr->entry.name = ((char *) ptr) + sizeof(*ptr); | |
188 | + memmove((char *) ptr->entry.name, name, len); | |
189 | + atomic_set(&ptr->head.users, 1); | |
190 | + tomoyo_fill_path_info(&ptr->entry); | |
191 | + list_add_tail(&ptr->head.list, head); | |
192 | + } else { | |
186 | 193 | kfree(ptr); |
187 | 194 | ptr = NULL; |
188 | - tomoyo_warn_oom(__func__); | |
189 | - goto out; | |
190 | 195 | } |
191 | - atomic_add(allocated_len, &tomoyo_policy_memory_size); | |
192 | - ptr->entry.name = ((char *) ptr) + sizeof(*ptr); | |
193 | - memmove((char *) ptr->entry.name, name, len); | |
194 | - atomic_set(&ptr->head.users, 1); | |
195 | - tomoyo_fill_path_info(&ptr->entry); | |
196 | - list_add_tail(&ptr->head.list, head); | |
197 | - out: | |
196 | +out: | |
198 | 197 | mutex_unlock(&tomoyo_policy_lock); |
199 | 198 | return ptr ? &ptr->entry : NULL; |
200 | 199 | } |
... | ... | @@ -226,67 +225,5 @@ |
226 | 225 | TOMOYO_TRANSITION_CONTROL_INITIALIZE); |
227 | 226 | } |
228 | 227 | #endif |
229 | -} | |
230 | - | |
231 | - | |
232 | -/* Memory allocated for query lists. */ | |
233 | -unsigned int tomoyo_query_memory_size; | |
234 | -/* Quota for holding query lists. */ | |
235 | -unsigned int tomoyo_quota_for_query; | |
236 | - | |
237 | -/** | |
238 | - * tomoyo_read_memory_counter - Check for memory usage in bytes. | |
239 | - * | |
240 | - * @head: Pointer to "struct tomoyo_io_buffer". | |
241 | - * | |
242 | - * Returns memory usage. | |
243 | - */ | |
244 | -void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) | |
245 | -{ | |
246 | - if (!head->r.eof) { | |
247 | - const unsigned int policy | |
248 | - = atomic_read(&tomoyo_policy_memory_size); | |
249 | - const unsigned int query = tomoyo_query_memory_size; | |
250 | - char buffer[64]; | |
251 | - | |
252 | - memset(buffer, 0, sizeof(buffer)); | |
253 | - if (tomoyo_quota_for_policy) | |
254 | - snprintf(buffer, sizeof(buffer) - 1, | |
255 | - " (Quota: %10u)", | |
256 | - tomoyo_quota_for_policy); | |
257 | - else | |
258 | - buffer[0] = '\0'; | |
259 | - tomoyo_io_printf(head, "Policy: %10u%s\n", policy, | |
260 | - buffer); | |
261 | - if (tomoyo_quota_for_query) | |
262 | - snprintf(buffer, sizeof(buffer) - 1, | |
263 | - " (Quota: %10u)", | |
264 | - tomoyo_quota_for_query); | |
265 | - else | |
266 | - buffer[0] = '\0'; | |
267 | - tomoyo_io_printf(head, "Query lists: %10u%s\n", query, | |
268 | - buffer); | |
269 | - tomoyo_io_printf(head, "Total: %10u\n", policy + query); | |
270 | - head->r.eof = true; | |
271 | - } | |
272 | -} | |
273 | - | |
274 | -/** | |
275 | - * tomoyo_write_memory_quota - Set memory quota. | |
276 | - * | |
277 | - * @head: Pointer to "struct tomoyo_io_buffer". | |
278 | - * | |
279 | - * Returns 0. | |
280 | - */ | |
281 | -int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head) | |
282 | -{ | |
283 | - char *data = head->write_buf; | |
284 | - unsigned int size; | |
285 | - | |
286 | - if (sscanf(data, "Policy: %u", &size) == 1) | |
287 | - tomoyo_quota_for_policy = size; | |
288 | - else if (sscanf(data, "Query lists: %u", &size) == 1) | |
289 | - tomoyo_quota_for_query = size; | |
290 | - return 0; | |
291 | 228 | } |
security/tomoyo/securityfs_if.c
... | ... | @@ -143,8 +143,8 @@ |
143 | 143 | TOMOYO_DOMAIN_STATUS); |
144 | 144 | tomoyo_create_entry(".process_status", 0600, tomoyo_dir, |
145 | 145 | TOMOYO_PROCESS_STATUS); |
146 | - tomoyo_create_entry("meminfo", 0600, tomoyo_dir, | |
147 | - TOMOYO_MEMINFO); | |
146 | + tomoyo_create_entry("stat", 0644, tomoyo_dir, | |
147 | + TOMOYO_STAT); | |
148 | 148 | tomoyo_create_entry("profile", 0600, tomoyo_dir, |
149 | 149 | TOMOYO_PROFILE); |
150 | 150 | tomoyo_create_entry("manager", 0600, tomoyo_dir, |
security/tomoyo/util.c
... | ... | @@ -47,6 +47,47 @@ |
47 | 47 | }; |
48 | 48 | |
49 | 49 | /** |
50 | + * tomoyo_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss. | |
51 | + * | |
52 | + * @time: Seconds since 1970/01/01 00:00:00. | |
53 | + * @stamp: Pointer to "struct tomoyo_time". | |
54 | + * | |
55 | + * Returns nothing. | |
56 | + * | |
57 | + * This function does not handle Y2038 problem. | |
58 | + */ | |
59 | +void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp) | |
60 | +{ | |
61 | + static const u16 tomoyo_eom[2][12] = { | |
62 | + { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, | |
63 | + { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } | |
64 | + }; | |
65 | + u16 y; | |
66 | + u8 m; | |
67 | + bool r; | |
68 | + stamp->sec = time % 60; | |
69 | + time /= 60; | |
70 | + stamp->min = time % 60; | |
71 | + time /= 60; | |
72 | + stamp->hour = time % 24; | |
73 | + time /= 24; | |
74 | + for (y = 1970; ; y++) { | |
75 | + const unsigned short days = (y & 3) ? 365 : 366; | |
76 | + if (time < days) | |
77 | + break; | |
78 | + time -= days; | |
79 | + } | |
80 | + r = (y & 3) == 0; | |
81 | + for (m = 0; m < 11 && time >= tomoyo_eom[r][m]; m++) | |
82 | + ; | |
83 | + if (m) | |
84 | + time -= tomoyo_eom[r][m - 1]; | |
85 | + stamp->year = y; | |
86 | + stamp->month = ++m; | |
87 | + stamp->day = ++time; | |
88 | +} | |
89 | + | |
90 | +/** | |
50 | 91 | * tomoyo_permstr - Find permission keywords. |
51 | 92 | * |
52 | 93 | * @string: String representation for permissions in foo/bar/buz format. |