1*1da177e4SLinus Torvalds /* proc.c: proc files for key database enumeration 2*1da177e4SLinus Torvalds * 3*1da177e4SLinus Torvalds * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 4*1da177e4SLinus Torvalds * Written by David Howells (dhowells@redhat.com) 5*1da177e4SLinus Torvalds * 6*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 7*1da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 8*1da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 9*1da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 10*1da177e4SLinus Torvalds */ 11*1da177e4SLinus Torvalds 12*1da177e4SLinus Torvalds #include <linux/module.h> 13*1da177e4SLinus Torvalds #include <linux/init.h> 14*1da177e4SLinus Torvalds #include <linux/sched.h> 15*1da177e4SLinus Torvalds #include <linux/slab.h> 16*1da177e4SLinus Torvalds #include <linux/fs.h> 17*1da177e4SLinus Torvalds #include <linux/proc_fs.h> 18*1da177e4SLinus Torvalds #include <linux/seq_file.h> 19*1da177e4SLinus Torvalds #include <asm/errno.h> 20*1da177e4SLinus Torvalds #include "internal.h" 21*1da177e4SLinus Torvalds 22*1da177e4SLinus Torvalds #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS 23*1da177e4SLinus Torvalds static int proc_keys_open(struct inode *inode, struct file *file); 24*1da177e4SLinus Torvalds static void *proc_keys_start(struct seq_file *p, loff_t *_pos); 25*1da177e4SLinus Torvalds static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos); 26*1da177e4SLinus Torvalds static void proc_keys_stop(struct seq_file *p, void *v); 27*1da177e4SLinus Torvalds static int proc_keys_show(struct seq_file *m, void *v); 28*1da177e4SLinus Torvalds 29*1da177e4SLinus Torvalds static struct seq_operations proc_keys_ops = { 30*1da177e4SLinus Torvalds .start = proc_keys_start, 31*1da177e4SLinus Torvalds .next = proc_keys_next, 32*1da177e4SLinus Torvalds .stop = proc_keys_stop, 33*1da177e4SLinus Torvalds .show = proc_keys_show, 34*1da177e4SLinus Torvalds }; 35*1da177e4SLinus Torvalds 36*1da177e4SLinus Torvalds static struct file_operations proc_keys_fops = { 37*1da177e4SLinus Torvalds .open = proc_keys_open, 38*1da177e4SLinus Torvalds .read = seq_read, 39*1da177e4SLinus Torvalds .llseek = seq_lseek, 40*1da177e4SLinus Torvalds .release = seq_release, 41*1da177e4SLinus Torvalds }; 42*1da177e4SLinus Torvalds #endif 43*1da177e4SLinus Torvalds 44*1da177e4SLinus Torvalds static int proc_key_users_open(struct inode *inode, struct file *file); 45*1da177e4SLinus Torvalds static void *proc_key_users_start(struct seq_file *p, loff_t *_pos); 46*1da177e4SLinus Torvalds static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos); 47*1da177e4SLinus Torvalds static void proc_key_users_stop(struct seq_file *p, void *v); 48*1da177e4SLinus Torvalds static int proc_key_users_show(struct seq_file *m, void *v); 49*1da177e4SLinus Torvalds 50*1da177e4SLinus Torvalds static struct seq_operations proc_key_users_ops = { 51*1da177e4SLinus Torvalds .start = proc_key_users_start, 52*1da177e4SLinus Torvalds .next = proc_key_users_next, 53*1da177e4SLinus Torvalds .stop = proc_key_users_stop, 54*1da177e4SLinus Torvalds .show = proc_key_users_show, 55*1da177e4SLinus Torvalds }; 56*1da177e4SLinus Torvalds 57*1da177e4SLinus Torvalds static struct file_operations proc_key_users_fops = { 58*1da177e4SLinus Torvalds .open = proc_key_users_open, 59*1da177e4SLinus Torvalds .read = seq_read, 60*1da177e4SLinus Torvalds .llseek = seq_lseek, 61*1da177e4SLinus Torvalds .release = seq_release, 62*1da177e4SLinus Torvalds }; 63*1da177e4SLinus Torvalds 64*1da177e4SLinus Torvalds /*****************************************************************************/ 65*1da177e4SLinus Torvalds /* 66*1da177e4SLinus Torvalds * declare the /proc files 67*1da177e4SLinus Torvalds */ 68*1da177e4SLinus Torvalds static int __init key_proc_init(void) 69*1da177e4SLinus Torvalds { 70*1da177e4SLinus Torvalds struct proc_dir_entry *p; 71*1da177e4SLinus Torvalds 72*1da177e4SLinus Torvalds #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS 73*1da177e4SLinus Torvalds p = create_proc_entry("keys", 0, NULL); 74*1da177e4SLinus Torvalds if (!p) 75*1da177e4SLinus Torvalds panic("Cannot create /proc/keys\n"); 76*1da177e4SLinus Torvalds 77*1da177e4SLinus Torvalds p->proc_fops = &proc_keys_fops; 78*1da177e4SLinus Torvalds #endif 79*1da177e4SLinus Torvalds 80*1da177e4SLinus Torvalds p = create_proc_entry("key-users", 0, NULL); 81*1da177e4SLinus Torvalds if (!p) 82*1da177e4SLinus Torvalds panic("Cannot create /proc/key-users\n"); 83*1da177e4SLinus Torvalds 84*1da177e4SLinus Torvalds p->proc_fops = &proc_key_users_fops; 85*1da177e4SLinus Torvalds 86*1da177e4SLinus Torvalds return 0; 87*1da177e4SLinus Torvalds 88*1da177e4SLinus Torvalds } /* end key_proc_init() */ 89*1da177e4SLinus Torvalds 90*1da177e4SLinus Torvalds __initcall(key_proc_init); 91*1da177e4SLinus Torvalds 92*1da177e4SLinus Torvalds /*****************************************************************************/ 93*1da177e4SLinus Torvalds /* 94*1da177e4SLinus Torvalds * implement "/proc/keys" to provides a list of the keys on the system 95*1da177e4SLinus Torvalds */ 96*1da177e4SLinus Torvalds #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS 97*1da177e4SLinus Torvalds 98*1da177e4SLinus Torvalds static int proc_keys_open(struct inode *inode, struct file *file) 99*1da177e4SLinus Torvalds { 100*1da177e4SLinus Torvalds return seq_open(file, &proc_keys_ops); 101*1da177e4SLinus Torvalds 102*1da177e4SLinus Torvalds } 103*1da177e4SLinus Torvalds 104*1da177e4SLinus Torvalds static void *proc_keys_start(struct seq_file *p, loff_t *_pos) 105*1da177e4SLinus Torvalds { 106*1da177e4SLinus Torvalds struct rb_node *_p; 107*1da177e4SLinus Torvalds loff_t pos = *_pos; 108*1da177e4SLinus Torvalds 109*1da177e4SLinus Torvalds spin_lock(&key_serial_lock); 110*1da177e4SLinus Torvalds 111*1da177e4SLinus Torvalds _p = rb_first(&key_serial_tree); 112*1da177e4SLinus Torvalds while (pos > 0 && _p) { 113*1da177e4SLinus Torvalds pos--; 114*1da177e4SLinus Torvalds _p = rb_next(_p); 115*1da177e4SLinus Torvalds } 116*1da177e4SLinus Torvalds 117*1da177e4SLinus Torvalds return _p; 118*1da177e4SLinus Torvalds 119*1da177e4SLinus Torvalds } 120*1da177e4SLinus Torvalds 121*1da177e4SLinus Torvalds static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos) 122*1da177e4SLinus Torvalds { 123*1da177e4SLinus Torvalds (*_pos)++; 124*1da177e4SLinus Torvalds return rb_next((struct rb_node *) v); 125*1da177e4SLinus Torvalds 126*1da177e4SLinus Torvalds } 127*1da177e4SLinus Torvalds 128*1da177e4SLinus Torvalds static void proc_keys_stop(struct seq_file *p, void *v) 129*1da177e4SLinus Torvalds { 130*1da177e4SLinus Torvalds spin_unlock(&key_serial_lock); 131*1da177e4SLinus Torvalds } 132*1da177e4SLinus Torvalds 133*1da177e4SLinus Torvalds static int proc_keys_show(struct seq_file *m, void *v) 134*1da177e4SLinus Torvalds { 135*1da177e4SLinus Torvalds struct rb_node *_p = v; 136*1da177e4SLinus Torvalds struct key *key = rb_entry(_p, struct key, serial_node); 137*1da177e4SLinus Torvalds struct timespec now; 138*1da177e4SLinus Torvalds unsigned long timo; 139*1da177e4SLinus Torvalds char xbuf[12]; 140*1da177e4SLinus Torvalds 141*1da177e4SLinus Torvalds now = current_kernel_time(); 142*1da177e4SLinus Torvalds 143*1da177e4SLinus Torvalds read_lock(&key->lock); 144*1da177e4SLinus Torvalds 145*1da177e4SLinus Torvalds /* come up with a suitable timeout value */ 146*1da177e4SLinus Torvalds if (key->expiry == 0) { 147*1da177e4SLinus Torvalds memcpy(xbuf, "perm", 5); 148*1da177e4SLinus Torvalds } 149*1da177e4SLinus Torvalds else if (now.tv_sec >= key->expiry) { 150*1da177e4SLinus Torvalds memcpy(xbuf, "expd", 5); 151*1da177e4SLinus Torvalds } 152*1da177e4SLinus Torvalds else { 153*1da177e4SLinus Torvalds timo = key->expiry - now.tv_sec; 154*1da177e4SLinus Torvalds 155*1da177e4SLinus Torvalds if (timo < 60) 156*1da177e4SLinus Torvalds sprintf(xbuf, "%lus", timo); 157*1da177e4SLinus Torvalds else if (timo < 60*60) 158*1da177e4SLinus Torvalds sprintf(xbuf, "%lum", timo / 60); 159*1da177e4SLinus Torvalds else if (timo < 60*60*24) 160*1da177e4SLinus Torvalds sprintf(xbuf, "%luh", timo / (60*60)); 161*1da177e4SLinus Torvalds else if (timo < 60*60*24*7) 162*1da177e4SLinus Torvalds sprintf(xbuf, "%lud", timo / (60*60*24)); 163*1da177e4SLinus Torvalds else 164*1da177e4SLinus Torvalds sprintf(xbuf, "%luw", timo / (60*60*24*7)); 165*1da177e4SLinus Torvalds } 166*1da177e4SLinus Torvalds 167*1da177e4SLinus Torvalds seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %06x %5d %5d %-9.9s ", 168*1da177e4SLinus Torvalds key->serial, 169*1da177e4SLinus Torvalds key->flags & KEY_FLAG_INSTANTIATED ? 'I' : '-', 170*1da177e4SLinus Torvalds key->flags & KEY_FLAG_REVOKED ? 'R' : '-', 171*1da177e4SLinus Torvalds key->flags & KEY_FLAG_DEAD ? 'D' : '-', 172*1da177e4SLinus Torvalds key->flags & KEY_FLAG_IN_QUOTA ? 'Q' : '-', 173*1da177e4SLinus Torvalds key->flags & KEY_FLAG_USER_CONSTRUCT ? 'U' : '-', 174*1da177e4SLinus Torvalds key->flags & KEY_FLAG_NEGATIVE ? 'N' : '-', 175*1da177e4SLinus Torvalds atomic_read(&key->usage), 176*1da177e4SLinus Torvalds xbuf, 177*1da177e4SLinus Torvalds key->perm, 178*1da177e4SLinus Torvalds key->uid, 179*1da177e4SLinus Torvalds key->gid, 180*1da177e4SLinus Torvalds key->type->name); 181*1da177e4SLinus Torvalds 182*1da177e4SLinus Torvalds if (key->type->describe) 183*1da177e4SLinus Torvalds key->type->describe(key, m); 184*1da177e4SLinus Torvalds seq_putc(m, '\n'); 185*1da177e4SLinus Torvalds 186*1da177e4SLinus Torvalds read_unlock(&key->lock); 187*1da177e4SLinus Torvalds 188*1da177e4SLinus Torvalds return 0; 189*1da177e4SLinus Torvalds 190*1da177e4SLinus Torvalds } 191*1da177e4SLinus Torvalds 192*1da177e4SLinus Torvalds #endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */ 193*1da177e4SLinus Torvalds 194*1da177e4SLinus Torvalds /*****************************************************************************/ 195*1da177e4SLinus Torvalds /* 196*1da177e4SLinus Torvalds * implement "/proc/key-users" to provides a list of the key users 197*1da177e4SLinus Torvalds */ 198*1da177e4SLinus Torvalds static int proc_key_users_open(struct inode *inode, struct file *file) 199*1da177e4SLinus Torvalds { 200*1da177e4SLinus Torvalds return seq_open(file, &proc_key_users_ops); 201*1da177e4SLinus Torvalds 202*1da177e4SLinus Torvalds } 203*1da177e4SLinus Torvalds 204*1da177e4SLinus Torvalds static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) 205*1da177e4SLinus Torvalds { 206*1da177e4SLinus Torvalds struct rb_node *_p; 207*1da177e4SLinus Torvalds loff_t pos = *_pos; 208*1da177e4SLinus Torvalds 209*1da177e4SLinus Torvalds spin_lock(&key_user_lock); 210*1da177e4SLinus Torvalds 211*1da177e4SLinus Torvalds _p = rb_first(&key_user_tree); 212*1da177e4SLinus Torvalds while (pos > 0 && _p) { 213*1da177e4SLinus Torvalds pos--; 214*1da177e4SLinus Torvalds _p = rb_next(_p); 215*1da177e4SLinus Torvalds } 216*1da177e4SLinus Torvalds 217*1da177e4SLinus Torvalds return _p; 218*1da177e4SLinus Torvalds 219*1da177e4SLinus Torvalds } 220*1da177e4SLinus Torvalds 221*1da177e4SLinus Torvalds static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) 222*1da177e4SLinus Torvalds { 223*1da177e4SLinus Torvalds (*_pos)++; 224*1da177e4SLinus Torvalds return rb_next((struct rb_node *) v); 225*1da177e4SLinus Torvalds 226*1da177e4SLinus Torvalds } 227*1da177e4SLinus Torvalds 228*1da177e4SLinus Torvalds static void proc_key_users_stop(struct seq_file *p, void *v) 229*1da177e4SLinus Torvalds { 230*1da177e4SLinus Torvalds spin_unlock(&key_user_lock); 231*1da177e4SLinus Torvalds } 232*1da177e4SLinus Torvalds 233*1da177e4SLinus Torvalds static int proc_key_users_show(struct seq_file *m, void *v) 234*1da177e4SLinus Torvalds { 235*1da177e4SLinus Torvalds struct rb_node *_p = v; 236*1da177e4SLinus Torvalds struct key_user *user = rb_entry(_p, struct key_user, node); 237*1da177e4SLinus Torvalds 238*1da177e4SLinus Torvalds seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n", 239*1da177e4SLinus Torvalds user->uid, 240*1da177e4SLinus Torvalds atomic_read(&user->usage), 241*1da177e4SLinus Torvalds atomic_read(&user->nkeys), 242*1da177e4SLinus Torvalds atomic_read(&user->nikeys), 243*1da177e4SLinus Torvalds user->qnkeys, 244*1da177e4SLinus Torvalds KEYQUOTA_MAX_KEYS, 245*1da177e4SLinus Torvalds user->qnbytes, 246*1da177e4SLinus Torvalds KEYQUOTA_MAX_BYTES 247*1da177e4SLinus Torvalds ); 248*1da177e4SLinus Torvalds 249*1da177e4SLinus Torvalds return 0; 250*1da177e4SLinus Torvalds 251*1da177e4SLinus Torvalds } 252