Blame view

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