1 /* $NetBSD: linux_sysctl.c,v 1.2 2002/02/20 17:02:48 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Mike Karels at Berkeley Software Design, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_sysctl.c 8.9 (Berkeley) 5/20/95 39 */ 40 41 /* 42 * sysctl system call. 43 */ 44 45 #include <sys/cdefs.h> 46 __KERNEL_RCSID(0, "$NetBSD: linux_sysctl.c,v 1.2 2002/02/20 17:02:48 christos Exp $"); 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/errno.h> 51 #include <sys/proc.h> 52 #include <sys/mount.h> 53 #include <sys/sysctl.h> 54 #include <sys/syscallargs.h> 55 56 #include <compat/linux/common/linux_types.h> 57 #include <compat/linux/common/linux_signal.h> 58 59 #include <compat/linux/linux_syscallargs.h> 60 #include <compat/linux/common/linux_sysctl.h> 61 62 int linux_kern_sysctl(int *, u_int, void *, size_t *, void *, size_t, 63 struct proc *); 64 int linux_vm_sysctl(int *, u_int, void *, size_t *, void *, size_t, 65 struct proc *); 66 int linux_net_sysctl(int *, u_int, void *, size_t *, void *, size_t, 67 struct proc *); 68 int linux_proc_sysctl(int *, u_int, void *, size_t *, void *, size_t, 69 struct proc *); 70 int linux_fs_sysctl(int *, u_int, void *, size_t *, void *, size_t, 71 struct proc *); 72 #ifdef DEBUG 73 int linux_debug_sysctl(int *, u_int, void *, size_t *, void *, size_t, 74 struct proc *); 75 #endif 76 int linux_dev_sysctl(int *, u_int, void *, size_t *, void *, size_t, 77 struct proc *); 78 int linux_bus_sysctl(int *, u_int, void *, size_t *, void *, size_t, 79 struct proc *); 80 81 int 82 linux_sys___sysctl(struct proc *p, void *v, register_t *retval) 83 { 84 struct linux_sys___sysctl_args /* { 85 syscallarg(struct linux___sysctl *) lsp; 86 } */ *uap = v; 87 struct linux___sysctl ls; 88 int error; 89 size_t savelen = 0, oldlen = 0; 90 sysctlfn *fn; 91 int name[CTL_MAXNAME]; 92 size_t *oldlenp; 93 94 95 if ((error = copyin(SCARG(uap, lsp), &ls, sizeof ls))) 96 return error; 97 /* 98 * all top-level sysctl names are non-terminal 99 */ 100 if (ls.nlen > CTL_MAXNAME || ls.nlen < 2) 101 return (EINVAL); 102 error = copyin(ls.name, &name, ls.nlen * sizeof(int)); 103 if (error) 104 return (error); 105 106 /* 107 * For all but CTL_PROC, must be root to change a value. 108 * For CTL_PROC, must be root, or owner of the proc (and not suid), 109 * this is checked in proc_sysctl() (once we know the targer proc). 110 */ 111 if (ls.newval != NULL && name[0] != CTL_PROC && 112 (error = suser(p->p_ucred, &p->p_acflag))) 113 return error; 114 115 switch (name[0]) { 116 case LINUX_CTL_KERN: 117 fn = linux_kern_sysctl; 118 break; 119 case LINUX_CTL_VM: 120 fn = linux_vm_sysctl; 121 break; 122 case LINUX_CTL_NET: 123 fn = linux_net_sysctl; 124 break; 125 case LINUX_CTL_PROC: 126 fn = linux_proc_sysctl; 127 break; 128 case LINUX_CTL_FS: 129 fn = linux_fs_sysctl; 130 break; 131 #ifdef DEBUG 132 case LINUX_CTL_DEBUG: 133 fn = linux_debug_sysctl; 134 break; 135 #endif 136 case LINUX_CTL_DEV: 137 fn = linux_dev_sysctl; 138 break; 139 case LINUX_CTL_BUS: 140 fn = linux_bus_sysctl; 141 break; 142 default: 143 return (EOPNOTSUPP); 144 } 145 146 /* 147 * XXX Hey, we wire `oldval', but what about `newval'? 148 */ 149 oldlenp = ls.oldlenp; 150 if (oldlenp) { 151 if ((error = copyin(oldlenp, &oldlen, sizeof(oldlen)))) 152 return (error); 153 oldlenp = &oldlen; 154 } 155 if (ls.oldval != NULL) { 156 error = uvm_vslock(p, ls.oldval, oldlen, 157 VM_PROT_READ|VM_PROT_WRITE); 158 savelen = oldlen; 159 } 160 error = (*fn)(name + 1, ls.nlen - 1, ls.oldval, oldlenp, ls.newval, 161 ls.newlen, p); 162 if (ls.oldval != NULL) 163 uvm_vsunlock(p, ls.oldval, savelen); 164 if (error) 165 return (error); 166 if (ls.oldlenp) 167 error = copyout(&oldlen, ls.oldlenp, sizeof(oldlen)); 168 return (error); 169 } 170 171 /* 172 * NOTE: DO NOT CHANGE THIS 173 * Linux makes assumptions about specific features being present with 174 * more recent kernels. Specifically, LinuxThreads use RT queued 175 * signals if the kernel release is bigger. Since we don't support them 176 * yet, the version needs to stay this way until we'd have the RT queued 177 * signals implemented. 178 */ 179 char linux_sysname[128] = "Linux"; 180 char linux_release[128] = "2.0.38"; 181 char linux_version[128] = "#0 Sun Apr 1 11:11:11 MET 2000"; 182 183 /* 184 * kernel related system variables. 185 */ 186 int 187 linux_kern_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 188 void *newp, size_t newlen, struct proc *p) 189 { 190 /* 191 * Note that we allow writing into this, so that userland 192 * programs can setup things as they see fit. This is suboptimal. 193 */ 194 switch (name[0]) { 195 case LINUX_KERN_OSTYPE: 196 return sysctl_string(oldp, oldlenp, newp, newlen, 197 linux_sysname, sizeof(linux_sysname)); 198 case LINUX_KERN_OSRELEASE: 199 return sysctl_string(oldp, oldlenp, newp, newlen, 200 linux_release, sizeof(linux_release)); 201 case LINUX_KERN_VERSION: 202 return sysctl_string(oldp, oldlenp, newp, newlen, 203 linux_version, sizeof(linux_version)); 204 default: 205 return EOPNOTSUPP; 206 } 207 } 208 209 /* 210 * hardware related system variables. 211 */ 212 int 213 linux_vm_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 214 void *newp, size_t newlen, struct proc *p) 215 { 216 return (EOPNOTSUPP); 217 } 218 219 int 220 linux_net_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 221 void *newp, size_t newlen, struct proc *p) 222 { 223 return (EOPNOTSUPP); 224 } 225 226 int 227 linux_proc_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 228 void *newp, size_t newlen, struct proc *p) 229 { 230 return (EOPNOTSUPP); 231 } 232 233 int 234 linux_fs_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 235 void *newp, size_t newlen, struct proc *p) 236 { 237 return (EOPNOTSUPP); 238 } 239 #ifdef DEBUG 240 int 241 linux_debug_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 242 void *newp, size_t newlen, struct proc *p) 243 { 244 return (EOPNOTSUPP); 245 } 246 #endif /* DEBUG */ 247 248 int 249 linux_dev_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 250 void *newp, size_t newlen, struct proc *p) 251 { 252 return (EOPNOTSUPP); 253 } 254 255 int 256 linux_bus_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 257 void *newp, size_t newlen, struct proc *p) 258 { 259 return (EOPNOTSUPP); 260 } 261