^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/sockios.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <net/ax25.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/inet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/notifier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/sysctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <net/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <net/arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Callsign/UID mapper. This is in kernel space for security on multi-amateur machines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static HLIST_HEAD(ax25_uid_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static DEFINE_RWLOCK(ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int ax25_uid_policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) EXPORT_SYMBOL(ax25_uid_policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) ax25_uid_assoc *ax25_findbyuid(kuid_t uid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ax25_uid_assoc *ax25_uid, *res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) read_lock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) ax25_uid_for_each(ax25_uid, &ax25_uid_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (uid_eq(ax25_uid->uid, uid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ax25_uid_hold(ax25_uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) res = ax25_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) read_unlock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) EXPORT_SYMBOL(ax25_findbyuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) ax25_uid_assoc *ax25_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ax25_uid_assoc *user;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned long res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) case SIOCAX25GETUID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) res = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) read_lock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ax25_uid_for_each(ax25_uid, &ax25_uid_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) res = from_kuid_munged(current_user_ns(), ax25_uid->uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) read_unlock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) case SIOCAX25ADDUID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) kuid_t sax25_kuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) sax25_kuid = make_kuid(current_user_ns(), sax->sax25_uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (!uid_valid(sax25_kuid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) user = ax25_findbyuid(sax25_kuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (user) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) ax25_uid_put(user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (sax->sax25_uid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) refcount_set(&ax25_uid->refcount, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) ax25_uid->uid = sax25_kuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ax25_uid->call = sax->sax25_call;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) write_lock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) hlist_add_head(&ax25_uid->uid_node, &ax25_uid_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) write_unlock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) case SIOCAX25DELUID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ax25_uid = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) write_lock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ax25_uid_for_each(ax25_uid, &ax25_uid_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (ax25_uid == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) write_unlock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) hlist_del_init(&ax25_uid->uid_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ax25_uid_put(ax25_uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) write_unlock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return -EINVAL; /*NOTREACHED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) __acquires(ax25_uid_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) read_lock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return seq_hlist_start_head(&ax25_uid_list, *pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static void *ax25_uid_seq_next(struct seq_file *seq, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return seq_hlist_next(v, &ax25_uid_list, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static void ax25_uid_seq_stop(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) __releases(ax25_uid_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) read_unlock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static int ax25_uid_seq_show(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) char buf[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (v == SEQ_START_TOKEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) seq_printf(seq, "Policy: %d\n", ax25_uid_policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct ax25_uid_assoc *pt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) pt = hlist_entry(v, struct ax25_uid_assoc, uid_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) seq_printf(seq, "%6d %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) from_kuid_munged(seq_user_ns(seq), pt->uid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ax2asc(buf, &pt->call));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) const struct seq_operations ax25_uid_seqops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .start = ax25_uid_seq_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .next = ax25_uid_seq_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .stop = ax25_uid_seq_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .show = ax25_uid_seq_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * Free all memory associated with UID/Callsign structures.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) void __exit ax25_uid_free(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ax25_uid_assoc *ax25_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) write_lock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) ax25_uid_for_each(ax25_uid, &ax25_uid_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) hlist_del_init(&ax25_uid->uid_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ax25_uid_put(ax25_uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) write_unlock(&ax25_uid_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }