at v2.6.34-rc4 339 lines 8.2 kB view raw
1/* proc.c: proc files for key database enumeration 2 * 3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12#include <linux/module.h> 13#include <linux/init.h> 14#include <linux/sched.h> 15#include <linux/fs.h> 16#include <linux/proc_fs.h> 17#include <linux/seq_file.h> 18#include <asm/errno.h> 19#include "internal.h" 20 21#ifdef CONFIG_KEYS_DEBUG_PROC_KEYS 22static int proc_keys_open(struct inode *inode, struct file *file); 23static void *proc_keys_start(struct seq_file *p, loff_t *_pos); 24static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos); 25static void proc_keys_stop(struct seq_file *p, void *v); 26static int proc_keys_show(struct seq_file *m, void *v); 27 28static const struct seq_operations proc_keys_ops = { 29 .start = proc_keys_start, 30 .next = proc_keys_next, 31 .stop = proc_keys_stop, 32 .show = proc_keys_show, 33}; 34 35static const struct file_operations proc_keys_fops = { 36 .open = proc_keys_open, 37 .read = seq_read, 38 .llseek = seq_lseek, 39 .release = seq_release, 40}; 41#endif 42 43static int proc_key_users_open(struct inode *inode, struct file *file); 44static void *proc_key_users_start(struct seq_file *p, loff_t *_pos); 45static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos); 46static void proc_key_users_stop(struct seq_file *p, void *v); 47static int proc_key_users_show(struct seq_file *m, void *v); 48 49static const struct seq_operations proc_key_users_ops = { 50 .start = proc_key_users_start, 51 .next = proc_key_users_next, 52 .stop = proc_key_users_stop, 53 .show = proc_key_users_show, 54}; 55 56static const struct file_operations proc_key_users_fops = { 57 .open = proc_key_users_open, 58 .read = seq_read, 59 .llseek = seq_lseek, 60 .release = seq_release, 61}; 62 63/*****************************************************************************/ 64/* 65 * declare the /proc files 66 */ 67static int __init key_proc_init(void) 68{ 69 struct proc_dir_entry *p; 70 71#ifdef CONFIG_KEYS_DEBUG_PROC_KEYS 72 p = proc_create("keys", 0, NULL, &proc_keys_fops); 73 if (!p) 74 panic("Cannot create /proc/keys\n"); 75#endif 76 77 p = proc_create("key-users", 0, NULL, &proc_key_users_fops); 78 if (!p) 79 panic("Cannot create /proc/key-users\n"); 80 81 return 0; 82 83} /* end key_proc_init() */ 84 85__initcall(key_proc_init); 86 87/*****************************************************************************/ 88/* 89 * implement "/proc/keys" to provides a list of the keys on the system 90 */ 91#ifdef CONFIG_KEYS_DEBUG_PROC_KEYS 92 93static struct rb_node *key_serial_next(struct rb_node *n) 94{ 95 struct user_namespace *user_ns = current_user_ns(); 96 97 n = rb_next(n); 98 while (n) { 99 struct key *key = rb_entry(n, struct key, serial_node); 100 if (key->user->user_ns == user_ns) 101 break; 102 n = rb_next(n); 103 } 104 return n; 105} 106 107static int proc_keys_open(struct inode *inode, struct file *file) 108{ 109 return seq_open(file, &proc_keys_ops); 110} 111 112static struct key *find_ge_key(key_serial_t id) 113{ 114 struct user_namespace *user_ns = current_user_ns(); 115 struct rb_node *n = key_serial_tree.rb_node; 116 struct key *minkey = NULL; 117 118 while (n) { 119 struct key *key = rb_entry(n, struct key, serial_node); 120 if (id < key->serial) { 121 if (!minkey || minkey->serial > key->serial) 122 minkey = key; 123 n = n->rb_left; 124 } else if (id > key->serial) { 125 n = n->rb_right; 126 } else { 127 minkey = key; 128 break; 129 } 130 key = NULL; 131 } 132 133 if (!minkey) 134 return NULL; 135 136 for (;;) { 137 if (minkey->user->user_ns == user_ns) 138 return minkey; 139 n = rb_next(&minkey->serial_node); 140 if (!n) 141 return NULL; 142 minkey = rb_entry(n, struct key, serial_node); 143 } 144} 145 146static void *proc_keys_start(struct seq_file *p, loff_t *_pos) 147 __acquires(key_serial_lock) 148{ 149 key_serial_t pos = *_pos; 150 struct key *key; 151 152 spin_lock(&key_serial_lock); 153 154 if (*_pos > INT_MAX) 155 return NULL; 156 key = find_ge_key(pos); 157 if (!key) 158 return NULL; 159 *_pos = key->serial; 160 return &key->serial_node; 161} 162 163static inline key_serial_t key_node_serial(struct rb_node *n) 164{ 165 struct key *key = rb_entry(n, struct key, serial_node); 166 return key->serial; 167} 168 169static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos) 170{ 171 struct rb_node *n; 172 173 n = key_serial_next(v); 174 if (n) 175 *_pos = key_node_serial(n); 176 return n; 177} 178 179static void proc_keys_stop(struct seq_file *p, void *v) 180 __releases(key_serial_lock) 181{ 182 spin_unlock(&key_serial_lock); 183} 184 185static int proc_keys_show(struct seq_file *m, void *v) 186{ 187 struct rb_node *_p = v; 188 struct key *key = rb_entry(_p, struct key, serial_node); 189 struct timespec now; 190 unsigned long timo; 191 char xbuf[12]; 192 int rc; 193 194 /* check whether the current task is allowed to view the key (assuming 195 * non-possession) 196 * - the caller holds a spinlock, and thus the RCU read lock, making our 197 * access to __current_cred() safe 198 */ 199 rc = key_task_permission(make_key_ref(key, 0), current_cred(), 200 KEY_VIEW); 201 if (rc < 0) 202 return 0; 203 204 now = current_kernel_time(); 205 206 rcu_read_lock(); 207 208 /* come up with a suitable timeout value */ 209 if (key->expiry == 0) { 210 memcpy(xbuf, "perm", 5); 211 } else if (now.tv_sec >= key->expiry) { 212 memcpy(xbuf, "expd", 5); 213 } else { 214 timo = key->expiry - now.tv_sec; 215 216 if (timo < 60) 217 sprintf(xbuf, "%lus", timo); 218 else if (timo < 60*60) 219 sprintf(xbuf, "%lum", timo / 60); 220 else if (timo < 60*60*24) 221 sprintf(xbuf, "%luh", timo / (60*60)); 222 else if (timo < 60*60*24*7) 223 sprintf(xbuf, "%lud", timo / (60*60*24)); 224 else 225 sprintf(xbuf, "%luw", timo / (60*60*24*7)); 226 } 227 228#define showflag(KEY, LETTER, FLAG) \ 229 (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-') 230 231 seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ", 232 key->serial, 233 showflag(key, 'I', KEY_FLAG_INSTANTIATED), 234 showflag(key, 'R', KEY_FLAG_REVOKED), 235 showflag(key, 'D', KEY_FLAG_DEAD), 236 showflag(key, 'Q', KEY_FLAG_IN_QUOTA), 237 showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT), 238 showflag(key, 'N', KEY_FLAG_NEGATIVE), 239 atomic_read(&key->usage), 240 xbuf, 241 key->perm, 242 key->uid, 243 key->gid, 244 key->type->name); 245 246#undef showflag 247 248 if (key->type->describe) 249 key->type->describe(key, m); 250 seq_putc(m, '\n'); 251 252 rcu_read_unlock(); 253 return 0; 254} 255 256#endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */ 257 258static struct rb_node *__key_user_next(struct rb_node *n) 259{ 260 while (n) { 261 struct key_user *user = rb_entry(n, struct key_user, node); 262 if (user->user_ns == current_user_ns()) 263 break; 264 n = rb_next(n); 265 } 266 return n; 267} 268 269static struct rb_node *key_user_next(struct rb_node *n) 270{ 271 return __key_user_next(rb_next(n)); 272} 273 274static struct rb_node *key_user_first(struct rb_root *r) 275{ 276 struct rb_node *n = rb_first(r); 277 return __key_user_next(n); 278} 279 280/*****************************************************************************/ 281/* 282 * implement "/proc/key-users" to provides a list of the key users 283 */ 284static int proc_key_users_open(struct inode *inode, struct file *file) 285{ 286 return seq_open(file, &proc_key_users_ops); 287} 288 289static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) 290 __acquires(key_user_lock) 291{ 292 struct rb_node *_p; 293 loff_t pos = *_pos; 294 295 spin_lock(&key_user_lock); 296 297 _p = key_user_first(&key_user_tree); 298 while (pos > 0 && _p) { 299 pos--; 300 _p = key_user_next(_p); 301 } 302 303 return _p; 304} 305 306static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) 307{ 308 (*_pos)++; 309 return key_user_next((struct rb_node *) v); 310} 311 312static void proc_key_users_stop(struct seq_file *p, void *v) 313 __releases(key_user_lock) 314{ 315 spin_unlock(&key_user_lock); 316} 317 318static int proc_key_users_show(struct seq_file *m, void *v) 319{ 320 struct rb_node *_p = v; 321 struct key_user *user = rb_entry(_p, struct key_user, node); 322 unsigned maxkeys = (user->uid == 0) ? 323 key_quota_root_maxkeys : key_quota_maxkeys; 324 unsigned maxbytes = (user->uid == 0) ? 325 key_quota_root_maxbytes : key_quota_maxbytes; 326 327 seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n", 328 user->uid, 329 atomic_read(&user->usage), 330 atomic_read(&user->nkeys), 331 atomic_read(&user->nikeys), 332 user->qnkeys, 333 maxkeys, 334 user->qnbytes, 335 maxbytes); 336 337 return 0; 338 339}