Blame view

net/ax25/ax25_uid.c 4.74 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
  /*
   * 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.
   *
   * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
   */
4fc268d24   Randy Dunlap   [PATCH] capable/c...
9
10
  
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
14
15
  #include <linux/errno.h>
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/in.h>
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
20
  #include <linux/timer.h>
  #include <linux/string.h>
  #include <linux/sockios.h>
  #include <linux/net.h>
  #include <linux/spinlock.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
27
28
29
30
31
32
  #include <net/ax25.h>
  #include <linux/inet.h>
  #include <linux/netdevice.h>
  #include <linux/if_arp.h>
  #include <linux/skbuff.h>
  #include <net/sock.h>
  #include <asm/uaccess.h>
  #include <asm/system.h>
  #include <linux/fcntl.h>
  #include <linux/mm.h>
  #include <linux/interrupt.h>
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
33
  #include <linux/list.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
39
  #include <linux/notifier.h>
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
  #include <linux/stat.h>
  #include <linux/netfilter.h>
  #include <linux/sysctl.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
40
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
  #include <net/ip.h>
  #include <net/arp.h>
  
  /*
   *	Callsign/UID mapper. This is in kernel space for security on multi-amateur machines.
   */
f16f3026d   Eric Dumazet   [AX25]: sparse cl...
47
  static HLIST_HEAD(ax25_uid_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
  static DEFINE_RWLOCK(ax25_uid_lock);
f16f3026d   Eric Dumazet   [AX25]: sparse cl...
49
  int ax25_uid_policy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50

70868eace   Ralf Baechle   [AX.25]: Move AX....
51
  EXPORT_SYMBOL(ax25_uid_policy);
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
52
  ax25_uid_assoc *ax25_findbyuid(uid_t uid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  {
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
54
55
  	ax25_uid_assoc *ax25_uid, *res = NULL;
  	struct hlist_node *node;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
  
  	read_lock(&ax25_uid_lock);
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
58
  	ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
  		if (ax25_uid->uid == uid) {
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
60
61
  			ax25_uid_hold(ax25_uid);
  			res = ax25_uid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
64
65
  			break;
  		}
  	}
  	read_unlock(&ax25_uid_lock);
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
66
  	return res;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
68
  EXPORT_SYMBOL(ax25_findbyuid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
  int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
  {
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
71
72
73
  	ax25_uid_assoc *ax25_uid;
  	struct hlist_node *node;
  	ax25_uid_assoc *user;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
77
78
79
  	unsigned long res;
  
  	switch (cmd) {
  	case SIOCAX25GETUID:
  		res = -ENOENT;
  		read_lock(&ax25_uid_lock);
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
80
  		ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
83
84
85
86
87
88
89
90
91
92
  			if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
  				res = ax25_uid->uid;
  				break;
  			}
  		}
  		read_unlock(&ax25_uid_lock);
  
  		return res;
  
  	case SIOCAX25ADDUID:
  		if (!capable(CAP_NET_ADMIN))
  			return -EPERM;
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
93
94
95
  		user = ax25_findbyuid(sax->sax25_uid);
  		if (user) {
  			ax25_uid_put(user);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  			return -EEXIST;
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
97
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
  		if (sax->sax25_uid == 0)
  			return -EINVAL;
  		if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL)
  			return -ENOMEM;
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
102
  		atomic_set(&ax25_uid->refcount, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
106
  		ax25_uid->uid  = sax->sax25_uid;
  		ax25_uid->call = sax->sax25_call;
  
  		write_lock(&ax25_uid_lock);
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
107
  		hlist_add_head(&ax25_uid->uid_node, &ax25_uid_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
110
111
112
113
114
  		write_unlock(&ax25_uid_lock);
  
  		return 0;
  
  	case SIOCAX25DELUID:
  		if (!capable(CAP_NET_ADMIN))
  			return -EPERM;
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
115
  		ax25_uid = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
  		write_lock(&ax25_uid_lock);
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
117
118
  		ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
  			if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
123
124
  		}
  		if (ax25_uid == NULL) {
  			write_unlock(&ax25_uid_lock);
  			return -ENOENT;
  		}
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
125
126
  		hlist_del_init(&ax25_uid->uid_node);
  		ax25_uid_put(ax25_uid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
  		write_unlock(&ax25_uid_lock);
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
128
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
131
132
133
134
135
136
137
138
139
  
  	default:
  		return -EINVAL;
  	}
  
  	return -EINVAL;	/*NOTREACHED */
  }
  
  #ifdef CONFIG_PROC_FS
  
  static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos)
f16f3026d   Eric Dumazet   [AX25]: sparse cl...
140
  	__acquires(ax25_uid_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  	read_lock(&ax25_uid_lock);
b512f3d84   Li Zefan   net: ax25: use se...
143
  	return seq_hlist_start_head(&ax25_uid_list, *pos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
146
147
  }
  
  static void *ax25_uid_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
b512f3d84   Li Zefan   net: ax25: use se...
148
  	return seq_hlist_next(v, &ax25_uid_list, pos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
150
151
  }
  
  static void ax25_uid_seq_stop(struct seq_file *seq, void *v)
f16f3026d   Eric Dumazet   [AX25]: sparse cl...
152
  	__releases(ax25_uid_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
157
158
  {
  	read_unlock(&ax25_uid_lock);
  }
  
  static int ax25_uid_seq_show(struct seq_file *seq, void *v)
  {
f75268cd6   Ralf Baechle   [AX25]: Make ax2a...
159
  	char buf[11];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
163
  	if (v == SEQ_START_TOKEN)
  		seq_printf(seq, "Policy: %d
  ", ax25_uid_policy);
  	else {
b512f3d84   Li Zefan   net: ax25: use se...
164
  		struct ax25_uid_assoc *pt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165

b512f3d84   Li Zefan   net: ax25: use se...
166
  		pt = hlist_entry(v, struct ax25_uid_assoc, uid_node);
f75268cd6   Ralf Baechle   [AX25]: Make ax2a...
167
168
  		seq_printf(seq, "%6d %s
  ", pt->uid, ax2asc(buf, &pt->call));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
171
  	}
  	return 0;
  }
56b3d975b   Philippe De Muyter   [NET]: Make all i...
172
  static const struct seq_operations ax25_uid_seqops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
174
175
176
177
178
179
180
181
182
  	.start = ax25_uid_seq_start,
  	.next = ax25_uid_seq_next,
  	.stop = ax25_uid_seq_stop,
  	.show = ax25_uid_seq_show,
  };
  
  static int ax25_uid_info_open(struct inode *inode, struct file *file)
  {
  	return seq_open(file, &ax25_uid_seqops);
  }
9a32144e9   Arjan van de Ven   [PATCH] mark stru...
183
  const struct file_operations ax25_uid_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
188
189
190
191
192
193
194
195
196
197
  	.owner = THIS_MODULE,
  	.open = ax25_uid_info_open,
  	.read = seq_read,
  	.llseek = seq_lseek,
  	.release = seq_release,
  };
  
  #endif
  
  /*
   *	Free all memory associated with UID/Callsign structures.
   */
  void __exit ax25_uid_free(void)
  {
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
198
199
  	ax25_uid_assoc *ax25_uid;
  	struct hlist_node *node;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
201
  
  	write_lock(&ax25_uid_lock);
ae1b6a31b   Pavel Emelyanov   [AX25]: Potential...
202
  again:
01d7dd0e9   Ralf Baechle   [AX25]: UID fixes
203
204
205
  	ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
  		hlist_del_init(&ax25_uid->uid_node);
  		ax25_uid_put(ax25_uid);
ae1b6a31b   Pavel Emelyanov   [AX25]: Potential...
206
  		goto again;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
  	write_unlock(&ax25_uid_lock);
  }