1 /* 2 * Copyright (c) 2000-2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /*- 29 * Copyright 1997,1998 Julian Elischer. All rights reserved. 30 * [email protected] 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions are 34 * met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright notice, 38 * this list of conditions and the following disclaimer in the documentation 39 * and/or other materials provided with the distribution. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS 42 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 43 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 44 * DISCLAIMED. IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR 45 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 47 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 48 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * devfs_vfsops.c 54 * 55 */ 56 /* 57 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 58 * support for mandatory and extensible security protections. This notice 59 * is included in support of clause 2.2 (b) of the Apple Public License, 60 * Version 2.0. 61 */ 62 /* 63 * HISTORY 64 * Dieter Siegmund ([email protected]) Wed Jul 14 13:37:59 PDT 1999 65 * - modified devfs_statfs() to use devfs_stats to calculate the 66 * amount of memory used by devfs 67 */ 68 69 70 #include <sys/param.h> 71 #include <sys/systm.h> 72 #include <sys/kernel.h> 73 #include <sys/vnode_internal.h> 74 #include <sys/proc.h> 75 #include <sys/kauth.h> 76 #include <sys/mount_internal.h> 77 #include <sys/malloc.h> 78 #include <sys/conf.h> 79 #include <libkern/OSAtomic.h> 80 #include <atm/atm_internal.h> 81 82 #if CONFIG_MACF 83 #include <security/mac_framework.h> 84 #endif 85 86 #include "devfs.h" 87 #include "devfsdefs.h" 88 89 #if FDESC 90 #include "fdesc.h" 91 #endif /* FDESC */ 92 93 94 static int devfs_statfs( struct mount *mp, struct vfsstatfs *sbp, vfs_context_t ctx); 95 static int devfs_vfs_getattr(mount_t mp, struct vfs_attr *fsap, vfs_context_t ctx); 96 97 #if CONFIG_DEV_KMEM 98 extern boolean_t dev_kmem_enabled; 99 #endif 100 101 /*- 102 * Called from the generic VFS startups. 103 * This is the second stage of DEVFS initialisation. 104 * The probed devices have already been loaded and the 105 * basic structure of the DEVFS created. 106 * We take the oportunity to mount the hidden DEVFS layer, so that 107 * devices from devfs get sync'd. 108 */ 109 static int 110 devfs_init(__unused struct vfsconf *vfsp) 111 { 112 if (devfs_sinit()) { 113 return ENOTSUP; 114 } 115 devfs_make_node(makedev(0, 0), DEVFS_CHAR, 116 UID_ROOT, GID_WHEEL, 0622, "console"); 117 devfs_make_node(makedev(2, 0), DEVFS_CHAR, 118 UID_ROOT, GID_WHEEL, 0666, "tty"); 119 #if CONFIG_DEV_KMEM 120 if (dev_kmem_enabled) { 121 /* (3,0) reserved for /dev/mem physical memory */ 122 devfs_make_node(makedev(3, 1), DEVFS_CHAR, 123 UID_ROOT, GID_KMEM, 0640, "kmem"); 124 } 125 #endif 126 devfs_make_node(makedev(3, 2), DEVFS_CHAR, 127 UID_ROOT, GID_WHEEL, 0666, "null"); 128 devfs_make_node(makedev(3, 3), DEVFS_CHAR, 129 UID_ROOT, GID_WHEEL, 0666, "zero"); 130 uint32_t logging_config = atm_get_diagnostic_config(); 131 132 devfs_make_node(makedev(6, 0), DEVFS_CHAR, 133 UID_ROOT, GID_WHEEL, 0600, "klog"); 134 135 if (!(logging_config & ATM_TRACE_DISABLE)) { 136 devfs_make_node(makedev(7, 0), DEVFS_CHAR, 137 UID_LOGD, GID_LOGD, 0600, "oslog"); 138 if (cdevsw_setkqueueok(7, (&(cdevsw[7])), 0) == -1) { 139 return ENOTSUP; 140 } 141 142 devfs_make_node(makedev(8, 0), DEVFS_CHAR, 143 UID_ROOT, GID_WHEEL, 0600, "oslog_stream"); 144 if (cdevsw_setkqueueok(8, (&(cdevsw[8])), 0) == -1) { 145 return ENOTSUP; 146 } 147 } 148 149 150 #if FDESC 151 devfs_fdesc_init(); 152 #endif 153 154 return 0; 155 } 156 157 /*- 158 * mp - pointer to 'mount' structure 159 * path - addr in user space of mount point (ie /usr or whatever) 160 * data - addr in user space of mount params including the 161 * name of the block special file to treat as a filesystem. 162 * (NOT USED) 163 * ndp - namei data pointer (NOT USED) 164 * p - proc pointer 165 * devfs is special in that it doesn't require any device to be mounted.. 166 * It makes up its data as it goes along. 167 * it must be mounted during single user.. until it is, only std{in/out/err} 168 * and the root filesystem are available. 169 */ 170 /*proto*/ 171 int 172 devfs_mount(struct mount *mp, __unused vnode_t devvp, __unused user_addr_t data, vfs_context_t ctx) 173 { 174 struct devfsmount *devfs_mp_p; /* devfs specific mount info */ 175 int error; 176 177 /*- 178 * If they just want to update, we don't need to do anything. 179 */ 180 if (mp->mnt_flag & MNT_UPDATE) { 181 return 0; 182 } 183 184 /* Advisory locking should be handled at the VFS layer */ 185 vfs_setlocklocal(mp); 186 187 /*- 188 * Well, it's not an update, it's a real mount request. 189 * Time to get dirty. 190 * HERE we should check to see if we are already mounted here. 191 */ 192 193 devfs_mp_p = kalloc_type(struct devfsmount, 194 Z_WAITOK | Z_ZERO | Z_NOFAIL); 195 devfs_mp_p->mount = mp; 196 197 /*- 198 * Fill out some fields 199 */ 200 __IGNORE_WCASTALIGN(mp->mnt_data = (qaddr_t)devfs_mp_p); 201 mp->mnt_vfsstat.f_fsid.val[0] = (int32_t)VM_KERNEL_ADDRHASH(devfs_mp_p); 202 mp->mnt_vfsstat.f_fsid.val[1] = vfs_typenum(mp); 203 mp->mnt_flag |= MNT_LOCAL; 204 205 DEVFS_LOCK(); 206 error = dev_dup_plane(devfs_mp_p); 207 DEVFS_UNLOCK(); 208 209 if (error) { 210 mp->mnt_data = (qaddr_t)0; 211 kfree_type(struct devfsmount, devfs_mp_p); 212 return error; 213 } else { 214 DEVFS_INCR_MOUNTS(); 215 } 216 217 /*- 218 * Copy in the name of the directory the filesystem 219 * is to be mounted on. 220 * And we clear the remainder of the character strings 221 * to be tidy. 222 */ 223 224 bzero(mp->mnt_vfsstat.f_mntfromname, MAXPATHLEN); 225 bcopy("devfs", mp->mnt_vfsstat.f_mntfromname, 5); 226 (void)devfs_statfs(mp, &mp->mnt_vfsstat, ctx); 227 228 return 0; 229 } 230 231 232 static int 233 devfs_start(__unused struct mount *mp, __unused int flags, __unused vfs_context_t ctx) 234 { 235 return 0; 236 } 237 238 /*- 239 * Unmount the filesystem described by mp. 240 */ 241 static int 242 devfs_unmount( struct mount *mp, int mntflags, __unused vfs_context_t ctx) 243 { 244 struct devfsmount *devfs_mp_p = (struct devfsmount *)mp->mnt_data; 245 int flags = 0; 246 int force = 0; 247 int error; 248 249 if (mntflags & MNT_FORCE) { 250 flags |= FORCECLOSE; 251 force = 1; 252 } 253 error = vflush(mp, NULLVP, flags); 254 if (error && !force) { 255 return error; 256 } 257 258 DEVFS_LOCK(); 259 devfs_free_plane(devfs_mp_p); 260 DEVFS_UNLOCK(); 261 262 DEVFS_DECR_MOUNTS(); 263 264 kfree_type(struct devfsmount, devfs_mp_p); 265 mp->mnt_data = (qaddr_t)0; 266 mp->mnt_flag &= ~MNT_LOCAL; 267 268 return 0; 269 } 270 271 /* return the address of the root vnode in *vpp */ 272 static int 273 devfs_root(struct mount *mp, struct vnode **vpp, __unused vfs_context_t ctx) 274 { 275 struct devfsmount *devfs_mp_p = (struct devfsmount *)(mp->mnt_data); 276 int error; 277 278 DEVFS_LOCK(); 279 /* last parameter to devfs_dntovn() is ignored */ 280 error = devfs_dntovn(devfs_mp_p->plane_root->de_dnp, vpp, NULL); 281 DEVFS_UNLOCK(); 282 283 return error; 284 } 285 286 static int 287 devfs_statfs( struct mount *mp, struct vfsstatfs *sbp, __unused vfs_context_t ctx) 288 { 289 struct devfsmount *devfs_mp_p = (struct devfsmount *)mp->mnt_data; 290 291 /*- 292 * Fill in the stat block. 293 */ 294 //sbp->f_type = mp->mnt_vfsstat.f_type; 295 sbp->f_flags = 0; /* XXX */ 296 sbp->f_bsize = 512; 297 sbp->f_iosize = 512; 298 sbp->f_blocks = (devfs_stats.mounts * sizeof(struct devfsmount) 299 + devfs_stats.nodes * sizeof(devnode_t) 300 + devfs_stats.entries * sizeof(devdirent_t) 301 + devfs_stats.stringspace 302 ) / sbp->f_bsize; 303 sbp->f_bfree = 0; 304 sbp->f_bavail = 0; 305 sbp->f_files = devfs_stats.nodes; 306 sbp->f_ffree = 0; 307 sbp->f_fsid.val[0] = (int32_t)VM_KERNEL_ADDRHASH(devfs_mp_p); 308 sbp->f_fsid.val[1] = vfs_typenum(mp); 309 310 return 0; 311 } 312 313 static int 314 devfs_vfs_getattr(__unused mount_t mp, struct vfs_attr *fsap, __unused vfs_context_t ctx) 315 { 316 VFSATTR_RETURN(fsap, f_objcount, devfs_stats.nodes); 317 VFSATTR_RETURN(fsap, f_maxobjcount, devfs_stats.nodes); 318 VFSATTR_RETURN(fsap, f_bsize, 512); 319 VFSATTR_RETURN(fsap, f_iosize, 512); 320 if (VFSATTR_IS_ACTIVE(fsap, f_blocks) || VFSATTR_IS_ACTIVE(fsap, f_bused)) { 321 fsap->f_blocks = (devfs_stats.mounts * sizeof(struct devfsmount) 322 + devfs_stats.nodes * sizeof(devnode_t) 323 + devfs_stats.entries * sizeof(devdirent_t) 324 + devfs_stats.stringspace 325 ) / fsap->f_bsize; 326 fsap->f_bused = fsap->f_blocks; 327 VFSATTR_SET_SUPPORTED(fsap, f_blocks); 328 VFSATTR_SET_SUPPORTED(fsap, f_bused); 329 } 330 VFSATTR_RETURN(fsap, f_bfree, 0); 331 VFSATTR_RETURN(fsap, f_bavail, 0); 332 VFSATTR_RETURN(fsap, f_files, devfs_stats.nodes); 333 VFSATTR_RETURN(fsap, f_ffree, 0); 334 VFSATTR_RETURN(fsap, f_fssubtype, 0); 335 336 if (VFSATTR_IS_ACTIVE(fsap, f_capabilities)) { 337 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_FORMAT] = 338 VOL_CAP_FMT_SYMBOLICLINKS | 339 VOL_CAP_FMT_HARDLINKS | 340 VOL_CAP_FMT_NO_ROOT_TIMES | 341 VOL_CAP_FMT_CASE_SENSITIVE | 342 VOL_CAP_FMT_CASE_PRESERVING | 343 VOL_CAP_FMT_FAST_STATFS | 344 VOL_CAP_FMT_2TB_FILESIZE | 345 VOL_CAP_FMT_HIDDEN_FILES; 346 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] = 347 VOL_CAP_INT_ATTRLIST; 348 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED1] = 0; 349 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED2] = 0; 350 351 fsap->f_capabilities.valid[VOL_CAPABILITIES_FORMAT] = 352 VOL_CAP_FMT_PERSISTENTOBJECTIDS | 353 VOL_CAP_FMT_SYMBOLICLINKS | 354 VOL_CAP_FMT_HARDLINKS | 355 VOL_CAP_FMT_JOURNAL | 356 VOL_CAP_FMT_JOURNAL_ACTIVE | 357 VOL_CAP_FMT_NO_ROOT_TIMES | 358 VOL_CAP_FMT_SPARSE_FILES | 359 VOL_CAP_FMT_ZERO_RUNS | 360 VOL_CAP_FMT_CASE_SENSITIVE | 361 VOL_CAP_FMT_CASE_PRESERVING | 362 VOL_CAP_FMT_FAST_STATFS | 363 VOL_CAP_FMT_2TB_FILESIZE | 364 VOL_CAP_FMT_OPENDENYMODES | 365 VOL_CAP_FMT_HIDDEN_FILES | 366 VOL_CAP_FMT_PATH_FROM_ID | 367 VOL_CAP_FMT_NO_VOLUME_SIZES; 368 fsap->f_capabilities.valid[VOL_CAPABILITIES_INTERFACES] = 369 VOL_CAP_INT_SEARCHFS | 370 VOL_CAP_INT_ATTRLIST | 371 VOL_CAP_INT_NFSEXPORT | 372 VOL_CAP_INT_READDIRATTR | 373 VOL_CAP_INT_EXCHANGEDATA | 374 VOL_CAP_INT_COPYFILE | 375 VOL_CAP_INT_ALLOCATE | 376 VOL_CAP_INT_VOL_RENAME | 377 VOL_CAP_INT_ADVLOCK | 378 VOL_CAP_INT_FLOCK | 379 VOL_CAP_INT_EXTENDED_SECURITY | 380 VOL_CAP_INT_USERACCESS | 381 VOL_CAP_INT_MANLOCK | 382 VOL_CAP_INT_EXTENDED_ATTR | 383 VOL_CAP_INT_NAMEDSTREAMS; 384 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED1] = 0; 385 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED2] = 0; 386 387 VFSATTR_SET_SUPPORTED(fsap, f_capabilities); 388 } 389 390 if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) { 391 fsap->f_attributes.validattr.commonattr = 392 ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | 393 ATTR_CMN_OBJTYPE | ATTR_CMN_OBJTAG | ATTR_CMN_OBJID | 394 ATTR_CMN_PAROBJID | 395 ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | ATTR_CMN_ACCTIME | 396 ATTR_CMN_OWNERID | ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK | 397 ATTR_CMN_FLAGS | ATTR_CMN_USERACCESS | ATTR_CMN_FILEID; 398 fsap->f_attributes.validattr.volattr = 399 ATTR_VOL_FSTYPE | ATTR_VOL_SIZE | ATTR_VOL_SPACEFREE | 400 ATTR_VOL_SPACEAVAIL | ATTR_VOL_MINALLOCATION | 401 ATTR_VOL_OBJCOUNT | ATTR_VOL_MAXOBJCOUNT | 402 ATTR_VOL_MOUNTPOINT | ATTR_VOL_MOUNTFLAGS | 403 ATTR_VOL_MOUNTEDDEVICE | ATTR_VOL_CAPABILITIES | 404 ATTR_VOL_ATTRIBUTES; 405 fsap->f_attributes.validattr.dirattr = 406 ATTR_DIR_LINKCOUNT | ATTR_DIR_MOUNTSTATUS; 407 fsap->f_attributes.validattr.fileattr = 408 ATTR_FILE_LINKCOUNT | ATTR_FILE_TOTALSIZE | 409 ATTR_FILE_IOBLOCKSIZE | ATTR_FILE_DEVTYPE | 410 ATTR_FILE_DATALENGTH; 411 fsap->f_attributes.validattr.forkattr = 0; 412 413 fsap->f_attributes.nativeattr.commonattr = 414 ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | 415 ATTR_CMN_OBJTYPE | ATTR_CMN_OBJTAG | ATTR_CMN_OBJID | 416 ATTR_CMN_PAROBJID | 417 ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | ATTR_CMN_ACCTIME | 418 ATTR_CMN_OWNERID | ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK | 419 ATTR_CMN_FLAGS | ATTR_CMN_USERACCESS | ATTR_CMN_FILEID; 420 fsap->f_attributes.nativeattr.volattr = 421 ATTR_VOL_FSTYPE | ATTR_VOL_SIZE | ATTR_VOL_SPACEFREE | 422 ATTR_VOL_SPACEAVAIL | ATTR_VOL_MINALLOCATION | 423 ATTR_VOL_OBJCOUNT | ATTR_VOL_MAXOBJCOUNT | 424 ATTR_VOL_MOUNTPOINT | ATTR_VOL_MOUNTFLAGS | 425 ATTR_VOL_MOUNTEDDEVICE | ATTR_VOL_CAPABILITIES | 426 ATTR_VOL_ATTRIBUTES; 427 fsap->f_attributes.nativeattr.dirattr = 428 ATTR_DIR_MOUNTSTATUS; 429 fsap->f_attributes.nativeattr.fileattr = 430 ATTR_FILE_LINKCOUNT | ATTR_FILE_TOTALSIZE | 431 ATTR_FILE_IOBLOCKSIZE | ATTR_FILE_DEVTYPE | 432 ATTR_FILE_DATALENGTH; 433 fsap->f_attributes.nativeattr.forkattr = 0; 434 435 VFSATTR_SET_SUPPORTED(fsap, f_attributes); 436 } 437 438 return 0; 439 } 440 441 static int 442 devfs_sync(__unused struct mount *mp, __unused int waitfor, __unused vfs_context_t ctx) 443 { 444 return 0; 445 } 446 447 448 static int 449 devfs_vget(__unused struct mount *mp, __unused ino64_t ino, __unused struct vnode **vpp, __unused vfs_context_t ctx) 450 { 451 return ENOTSUP; 452 } 453 454 /************************************************************* 455 * The concept of exporting a kernel generated devfs is stupid 456 * So don't handle filehandles 457 */ 458 459 static int 460 devfs_fhtovp(__unused struct mount *mp, __unused int fhlen, __unused unsigned char *fhp, __unused struct vnode **vpp, __unused vfs_context_t ctx) 461 { 462 return EINVAL; 463 } 464 465 466 static int 467 devfs_vptofh(__unused struct vnode *vp, __unused int *fhlenp, __unused unsigned char *fhp, __unused vfs_context_t ctx) 468 { 469 return EINVAL; 470 } 471 472 static int 473 devfs_sysctl(__unused int *name, __unused u_int namelen, __unused user_addr_t oldp, 474 __unused size_t *oldlenp, __unused user_addr_t newp, 475 __unused size_t newlen, __unused vfs_context_t ctx) 476 { 477 return ENOTSUP; 478 } 479 480 #include <sys/namei.h> 481 482 /* 483 * Function: devfs_kernel_mount 484 * Purpose: 485 * Mount devfs at the given mount point from within the kernel. 486 */ 487 int 488 devfs_kernel_mount(char * mntname) 489 { 490 int error; 491 vfs_context_t ctx = vfs_context_kernel(); 492 char fsname[] = "devfs"; 493 494 error = kernel_mount(fsname, NULLVP, NULLVP, mntname, NULL, 0, MNT_DONTBROWSE, KERNEL_MOUNT_NOAUTH | KERNEL_MOUNT_DEVFS, ctx); 495 if (error) { 496 printf("devfs_kernel_mount: kernel_mount failed: %d\n", error); 497 return error; 498 } 499 500 return 0; 501 } 502 503 const struct vfsops devfs_vfsops = { 504 .vfs_mount = devfs_mount, 505 .vfs_start = devfs_start, 506 .vfs_unmount = devfs_unmount, 507 .vfs_root = devfs_root, 508 .vfs_getattr = devfs_vfs_getattr, 509 .vfs_sync = devfs_sync, 510 .vfs_vget = devfs_vget, 511 .vfs_fhtovp = devfs_fhtovp, 512 .vfs_vptofh = devfs_vptofh, 513 .vfs_init = devfs_init, 514 .vfs_sysctl = devfs_sysctl, 515 // There are other VFS ops that we do not support 516 }; 517