11da177e4SLinus Torvalds /* proc.c: proc files for key database enumeration 21da177e4SLinus Torvalds * 31da177e4SLinus Torvalds * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 41da177e4SLinus Torvalds * Written by David Howells (dhowells@redhat.com) 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 71da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 81da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 91da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds #include <linux/module.h> 131da177e4SLinus Torvalds #include <linux/init.h> 141da177e4SLinus Torvalds #include <linux/sched.h> 151da177e4SLinus Torvalds #include <linux/slab.h> 161da177e4SLinus Torvalds #include <linux/fs.h> 171da177e4SLinus Torvalds #include <linux/proc_fs.h> 181da177e4SLinus Torvalds #include <linux/seq_file.h> 191da177e4SLinus Torvalds #include <asm/errno.h> 201da177e4SLinus Torvalds #include "internal.h" 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS 231da177e4SLinus Torvalds static int proc_keys_open(struct inode *inode, struct file *file); 241da177e4SLinus Torvalds static void *proc_keys_start(struct seq_file *p, loff_t *_pos); 251da177e4SLinus Torvalds static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos); 261da177e4SLinus Torvalds static void proc_keys_stop(struct seq_file *p, void *v); 271da177e4SLinus Torvalds static int proc_keys_show(struct seq_file *m, void *v); 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds static struct seq_operations proc_keys_ops = { 301da177e4SLinus Torvalds .start = proc_keys_start, 311da177e4SLinus Torvalds .next = proc_keys_next, 321da177e4SLinus Torvalds .stop = proc_keys_stop, 331da177e4SLinus Torvalds .show = proc_keys_show, 341da177e4SLinus Torvalds }; 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds static struct file_operations proc_keys_fops = { 371da177e4SLinus Torvalds .open = proc_keys_open, 381da177e4SLinus Torvalds .read = seq_read, 391da177e4SLinus Torvalds .llseek = seq_lseek, 401da177e4SLinus Torvalds .release = seq_release, 411da177e4SLinus Torvalds }; 421da177e4SLinus Torvalds #endif 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds static int proc_key_users_open(struct inode *inode, struct file *file); 451da177e4SLinus Torvalds static void *proc_key_users_start(struct seq_file *p, loff_t *_pos); 461da177e4SLinus Torvalds static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos); 471da177e4SLinus Torvalds static void proc_key_users_stop(struct seq_file *p, void *v); 481da177e4SLinus Torvalds static int proc_key_users_show(struct seq_file *m, void *v); 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds static struct seq_operations proc_key_users_ops = { 511da177e4SLinus Torvalds .start = proc_key_users_start, 521da177e4SLinus Torvalds .next = proc_key_users_next, 531da177e4SLinus Torvalds .stop = proc_key_users_stop, 541da177e4SLinus Torvalds .show = proc_key_users_show, 551da177e4SLinus Torvalds }; 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds static struct file_operations proc_key_users_fops = { 581da177e4SLinus Torvalds .open = proc_key_users_open, 591da177e4SLinus Torvalds .read = seq_read, 601da177e4SLinus Torvalds .llseek = seq_lseek, 611da177e4SLinus Torvalds .release = seq_release, 621da177e4SLinus Torvalds }; 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds /*****************************************************************************/ 651da177e4SLinus Torvalds /* 661da177e4SLinus Torvalds * declare the /proc files 671da177e4SLinus Torvalds */ 681da177e4SLinus Torvalds static int __init key_proc_init(void) 691da177e4SLinus Torvalds { 701da177e4SLinus Torvalds struct proc_dir_entry *p; 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS 731da177e4SLinus Torvalds p = create_proc_entry("keys", 0, NULL); 741da177e4SLinus Torvalds if (!p) 751da177e4SLinus Torvalds panic("Cannot create /proc/keys\n"); 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds p->proc_fops = &proc_keys_fops; 781da177e4SLinus Torvalds #endif 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds p = create_proc_entry("key-users", 0, NULL); 811da177e4SLinus Torvalds if (!p) 821da177e4SLinus Torvalds panic("Cannot create /proc/key-users\n"); 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds p->proc_fops = &proc_key_users_fops; 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds return 0; 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds } /* end key_proc_init() */ 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds __initcall(key_proc_init); 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds /*****************************************************************************/ 931da177e4SLinus Torvalds /* 941da177e4SLinus Torvalds * implement "/proc/keys" to provides a list of the keys on the system 951da177e4SLinus Torvalds */ 961da177e4SLinus Torvalds #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds static int proc_keys_open(struct inode *inode, struct file *file) 991da177e4SLinus Torvalds { 1001da177e4SLinus Torvalds return seq_open(file, &proc_keys_ops); 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds } 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds static void *proc_keys_start(struct seq_file *p, loff_t *_pos) 1051da177e4SLinus Torvalds { 1061da177e4SLinus Torvalds struct rb_node *_p; 1071da177e4SLinus Torvalds loff_t pos = *_pos; 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds spin_lock(&key_serial_lock); 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds _p = rb_first(&key_serial_tree); 1121da177e4SLinus Torvalds while (pos > 0 && _p) { 1131da177e4SLinus Torvalds pos--; 1141da177e4SLinus Torvalds _p = rb_next(_p); 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds return _p; 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds } 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos) 1221da177e4SLinus Torvalds { 1231da177e4SLinus Torvalds (*_pos)++; 1241da177e4SLinus Torvalds return rb_next((struct rb_node *) v); 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds } 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds static void proc_keys_stop(struct seq_file *p, void *v) 1291da177e4SLinus Torvalds { 1301da177e4SLinus Torvalds spin_unlock(&key_serial_lock); 1311da177e4SLinus Torvalds } 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds static int proc_keys_show(struct seq_file *m, void *v) 1341da177e4SLinus Torvalds { 1351da177e4SLinus Torvalds struct rb_node *_p = v; 1361da177e4SLinus Torvalds struct key *key = rb_entry(_p, struct key, serial_node); 1371da177e4SLinus Torvalds struct timespec now; 1381da177e4SLinus Torvalds unsigned long timo; 1391da177e4SLinus Torvalds char xbuf[12]; 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds now = current_kernel_time(); 1421da177e4SLinus Torvalds 143*76d8aeabSDavid Howells rcu_read_lock(); 1441da177e4SLinus Torvalds 1451da177e4SLinus Torvalds /* come up with a suitable timeout value */ 1461da177e4SLinus Torvalds if (key->expiry == 0) { 1471da177e4SLinus Torvalds memcpy(xbuf, "perm", 5); 1481da177e4SLinus Torvalds } 1491da177e4SLinus Torvalds else if (now.tv_sec >= key->expiry) { 1501da177e4SLinus Torvalds memcpy(xbuf, "expd", 5); 1511da177e4SLinus Torvalds } 1521da177e4SLinus Torvalds else { 1531da177e4SLinus Torvalds timo = key->expiry - now.tv_sec; 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds if (timo < 60) 1561da177e4SLinus Torvalds sprintf(xbuf, "%lus", timo); 1571da177e4SLinus Torvalds else if (timo < 60*60) 1581da177e4SLinus Torvalds sprintf(xbuf, "%lum", timo / 60); 1591da177e4SLinus Torvalds else if (timo < 60*60*24) 1601da177e4SLinus Torvalds sprintf(xbuf, "%luh", timo / (60*60)); 1611da177e4SLinus Torvalds else if (timo < 60*60*24*7) 1621da177e4SLinus Torvalds sprintf(xbuf, "%lud", timo / (60*60*24)); 1631da177e4SLinus Torvalds else 1641da177e4SLinus Torvalds sprintf(xbuf, "%luw", timo / (60*60*24*7)); 1651da177e4SLinus Torvalds } 1661da177e4SLinus Torvalds 167*76d8aeabSDavid Howells #define showflag(KEY, LETTER, FLAG) \ 168*76d8aeabSDavid Howells (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-') 169*76d8aeabSDavid Howells 1701da177e4SLinus Torvalds seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %06x %5d %5d %-9.9s ", 1711da177e4SLinus Torvalds key->serial, 172*76d8aeabSDavid Howells showflag(key, 'I', KEY_FLAG_INSTANTIATED), 173*76d8aeabSDavid Howells showflag(key, 'R', KEY_FLAG_REVOKED), 174*76d8aeabSDavid Howells showflag(key, 'D', KEY_FLAG_DEAD), 175*76d8aeabSDavid Howells showflag(key, 'Q', KEY_FLAG_IN_QUOTA), 176*76d8aeabSDavid Howells showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT), 177*76d8aeabSDavid Howells showflag(key, 'N', KEY_FLAG_NEGATIVE), 1781da177e4SLinus Torvalds atomic_read(&key->usage), 1791da177e4SLinus Torvalds xbuf, 1801da177e4SLinus Torvalds key->perm, 1811da177e4SLinus Torvalds key->uid, 1821da177e4SLinus Torvalds key->gid, 1831da177e4SLinus Torvalds key->type->name); 1841da177e4SLinus Torvalds 185*76d8aeabSDavid Howells #undef showflag 186*76d8aeabSDavid Howells 1871da177e4SLinus Torvalds if (key->type->describe) 1881da177e4SLinus Torvalds key->type->describe(key, m); 1891da177e4SLinus Torvalds seq_putc(m, '\n'); 1901da177e4SLinus Torvalds 191*76d8aeabSDavid Howells rcu_read_unlock(); 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds return 0; 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds } 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds #endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */ 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds /*****************************************************************************/ 2001da177e4SLinus Torvalds /* 2011da177e4SLinus Torvalds * implement "/proc/key-users" to provides a list of the key users 2021da177e4SLinus Torvalds */ 2031da177e4SLinus Torvalds static int proc_key_users_open(struct inode *inode, struct file *file) 2041da177e4SLinus Torvalds { 2051da177e4SLinus Torvalds return seq_open(file, &proc_key_users_ops); 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds } 2081da177e4SLinus Torvalds 2091da177e4SLinus Torvalds static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) 2101da177e4SLinus Torvalds { 2111da177e4SLinus Torvalds struct rb_node *_p; 2121da177e4SLinus Torvalds loff_t pos = *_pos; 2131da177e4SLinus Torvalds 2141da177e4SLinus Torvalds spin_lock(&key_user_lock); 2151da177e4SLinus Torvalds 2161da177e4SLinus Torvalds _p = rb_first(&key_user_tree); 2171da177e4SLinus Torvalds while (pos > 0 && _p) { 2181da177e4SLinus Torvalds pos--; 2191da177e4SLinus Torvalds _p = rb_next(_p); 2201da177e4SLinus Torvalds } 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds return _p; 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds } 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvalds static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) 2271da177e4SLinus Torvalds { 2281da177e4SLinus Torvalds (*_pos)++; 2291da177e4SLinus Torvalds return rb_next((struct rb_node *) v); 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds } 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds static void proc_key_users_stop(struct seq_file *p, void *v) 2341da177e4SLinus Torvalds { 2351da177e4SLinus Torvalds spin_unlock(&key_user_lock); 2361da177e4SLinus Torvalds } 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds static int proc_key_users_show(struct seq_file *m, void *v) 2391da177e4SLinus Torvalds { 2401da177e4SLinus Torvalds struct rb_node *_p = v; 2411da177e4SLinus Torvalds struct key_user *user = rb_entry(_p, struct key_user, node); 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvalds seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n", 2441da177e4SLinus Torvalds user->uid, 2451da177e4SLinus Torvalds atomic_read(&user->usage), 2461da177e4SLinus Torvalds atomic_read(&user->nkeys), 2471da177e4SLinus Torvalds atomic_read(&user->nikeys), 2481da177e4SLinus Torvalds user->qnkeys, 2491da177e4SLinus Torvalds KEYQUOTA_MAX_KEYS, 2501da177e4SLinus Torvalds user->qnbytes, 2511da177e4SLinus Torvalds KEYQUOTA_MAX_BYTES 2521da177e4SLinus Torvalds ); 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds return 0; 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds } 257