2  * Copyright (c) 2000-2010 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   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. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  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. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29  * Copyright 1997,1998 Julian Elischer.  All rights reserved. 
  32  * Redistribution and use in source and binary forms, with or without 
  33  * modification, are permitted provided that the following conditions are 
  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. 
  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 
  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, 
  64  *  Dieter Siegmund (dieter@apple.com) 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 
  70 #include <sys/param.h> 
  71 #include <sys/systm.h> 
  72 #include <sys/kernel.h> 
  73 #include <sys/vnode_internal.h> 
  75 #include <sys/kauth.h> 
  76 #include <sys/mount_internal.h> 
  77 #include <sys/malloc.h> 
  79 #include <libkern/OSAtomic.h> 
  80 #include <atm/atm_internal.h> 
  83 #include <security/mac_framework.h> 
  87 #include "devfsdefs.h" 
  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
); 
  98 extern boolean_t dev_kmem_enabled
; 
 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. 
 110 devfs_init(__unused 
struct vfsconf 
*vfsp
) 
 114         devfs_make_node(makedev(0, 0), DEVFS_CHAR
,  
 115                                         UID_ROOT
, GID_WHEEL
, 0622, "console"); 
 116         devfs_make_node(makedev(2, 0), DEVFS_CHAR
,  
 117                                         UID_ROOT
, GID_WHEEL
, 0666, "tty"); 
 119         if (dev_kmem_enabled
) { 
 120                 /* (3,0) reserved for /dev/mem physical memory */ 
 121                 devfs_make_node(makedev(3, 1), DEVFS_CHAR
,  
 122                                                 UID_ROOT
, GID_KMEM
, 0640, "kmem"); 
 125         devfs_make_node(makedev(3, 2), DEVFS_CHAR
,  
 126                                         UID_ROOT
, GID_WHEEL
, 0666, "null"); 
 127         devfs_make_node(makedev(3, 3), DEVFS_CHAR
,  
 128                                         UID_ROOT
, GID_WHEEL
, 0666, "zero"); 
 129         uint32_t logging_config 
= atm_get_diagnostic_config(); 
 131         devfs_make_node(makedev(6, 0), DEVFS_CHAR
, 
 132                                         UID_ROOT
, GID_WHEEL
, 0600, "klog"); 
 134         if ( !(logging_config 
& ATM_TRACE_DISABLE
) ) { 
 135                 devfs_make_node(makedev(7, 0), DEVFS_CHAR
, 
 136                                         UID_ROOT
, GID_WHEEL
, 0600, "oslog"); 
 137                 if (cdevsw_setkqueueok(7, (&(cdevsw
[7])), 0) == -1) { 
 141                 devfs_make_node(makedev(8, 0), DEVFS_CHAR
, 
 142                                         UID_ROOT
, GID_WHEEL
, 0600, "oslog_stream"); 
 143                 if (cdevsw_setkqueueok(8, (&(cdevsw
[8])), 0) == -1) { 
 157  *  mp   - pointer to 'mount' structure 
 158  *  path - addr in user space of mount point (ie /usr or whatever) 
 159  *  data - addr in user space of mount params including the 
 160  *         name of the block special file to treat as a filesystem. 
 162  *  ndp  - namei data pointer (NOT USED) 
 164  * devfs is special in that it doesn't require any device to be mounted.. 
 165  * It makes up its data as it goes along. 
 166  * it must be mounted during single user.. until it is, only std{in/out/err} 
 167  * and the root filesystem are available. 
 171 devfs_mount(struct mount 
*mp
, __unused vnode_t devvp
, __unused user_addr_t data
, vfs_context_t ctx
) 
 173         struct devfsmount 
*devfs_mp_p
;  /* devfs specific mount info */ 
 177          *  If they just want to update, we don't need to do anything. 
 179         if (mp
->mnt_flag 
& MNT_UPDATE
) 
 184         /* Advisory locking should be handled at the VFS layer */ 
 185         vfs_setlocklocal(mp
); 
 188          *  Well, it's not an update, it's a real mount request. 
 190          * HERE we should check to see if we are already mounted here. 
 193         MALLOC(devfs_mp_p
, struct devfsmount 
*, sizeof(struct devfsmount
), 
 194                M_DEVFSMNT
, M_WAITOK
); 
 195         if (devfs_mp_p 
== NULL
) 
 197         bzero(devfs_mp_p
,sizeof(*devfs_mp_p
)); 
 198         devfs_mp_p
->mount 
= mp
; 
 201          *  Fill out some fields 
 203         __IGNORE_WCASTALIGN(mp
->mnt_data 
= (qaddr_t
)devfs_mp_p
); 
 204         mp
->mnt_vfsstat
.f_fsid
.val
[0] = (int32_t)(uintptr_t)devfs_mp_p
; 
 205         mp
->mnt_vfsstat
.f_fsid
.val
[1] = vfs_typenum(mp
); 
 206         mp
->mnt_flag 
|= MNT_LOCAL
; 
 209         error 
= dev_dup_plane(devfs_mp_p
); 
 213                 mp
->mnt_data 
= (qaddr_t
)0; 
 214                 FREE((caddr_t
)devfs_mp_p
, M_DEVFSMNT
); 
 220          *  Copy in the name of the directory the filesystem 
 221          *  is to be mounted on. 
 222          *  And we clear the remainder of the character strings 
 226         bzero(mp
->mnt_vfsstat
.f_mntfromname
, MAXPATHLEN
); 
 227         bcopy("devfs",mp
->mnt_vfsstat
.f_mntfromname
, 5); 
 228         (void)devfs_statfs(mp
, &mp
->mnt_vfsstat
, ctx
); 
 235 devfs_start(__unused 
struct mount 
*mp
, __unused 
int flags
, __unused vfs_context_t ctx
) 
 241  *  Unmount the filesystem described by mp. 
 244 devfs_unmount( struct mount 
*mp
, int mntflags
, __unused vfs_context_t ctx
) 
 246         struct devfsmount 
*devfs_mp_p 
= (struct devfsmount 
*)mp
->mnt_data
; 
 251         if (mntflags 
& MNT_FORCE
) { 
 255         error 
= vflush(mp
, NULLVP
, flags
); 
 260         devfs_free_plane(devfs_mp_p
); 
 265         FREE((caddr_t
)devfs_mp_p
, M_DEVFSMNT
); 
 266         mp
->mnt_data 
= (qaddr_t
)0; 
 267         mp
->mnt_flag 
&= ~MNT_LOCAL
; 
 272 /* return the address of the root vnode  in *vpp */ 
 274 devfs_root(struct mount 
*mp
, struct vnode 
**vpp
, __unused vfs_context_t ctx
) 
 276         struct devfsmount 
*devfs_mp_p 
= (struct devfsmount 
*)(mp
->mnt_data
); 
 280         /* last parameter to devfs_dntovn() is ignored */ 
 281         error 
= devfs_dntovn(devfs_mp_p
->plane_root
->de_dnp
, vpp
, NULL
); 
 288 devfs_statfs( struct mount 
*mp
, struct vfsstatfs 
*sbp
, __unused vfs_context_t ctx
) 
 290         struct devfsmount 
*devfs_mp_p 
= (struct devfsmount 
*)mp
->mnt_data
; 
 293          *  Fill in the stat block. 
 295         //sbp->f_type   = mp->mnt_vfsstat.f_type; 
 296         sbp
->f_flags  
= 0;              /* XXX */ 
 299         sbp
->f_blocks 
= (devfs_stats
.mounts 
* sizeof(struct devfsmount
) 
 300                          + devfs_stats
.nodes 
* sizeof(devnode_t
) 
 301                          + devfs_stats
.entries 
* sizeof(devdirent_t
) 
 302                          + devfs_stats
.stringspace
 
 306         sbp
->f_files  
= devfs_stats
.nodes
; 
 308         sbp
->f_fsid
.val
[0] = (int32_t)(uintptr_t)devfs_mp_p
; 
 309         sbp
->f_fsid
.val
[1] = vfs_typenum(mp
); 
 315 devfs_vfs_getattr(__unused mount_t mp
, struct vfs_attr 
*fsap
, __unused vfs_context_t ctx
) 
 317         VFSATTR_RETURN(fsap
, f_objcount
, devfs_stats
.nodes
); 
 318         VFSATTR_RETURN(fsap
, f_maxobjcount
, devfs_stats
.nodes
); 
 319         VFSATTR_RETURN(fsap
, f_bsize
, 512); 
 320         VFSATTR_RETURN(fsap
, f_iosize
, 512); 
 321         if (VFSATTR_IS_ACTIVE(fsap
, f_blocks
) || VFSATTR_IS_ACTIVE(fsap
, f_bused
)) { 
 322                 fsap
->f_blocks 
= (devfs_stats
.mounts 
* sizeof(struct devfsmount
) 
 323                          + devfs_stats
.nodes 
* sizeof(devnode_t
) 
 324                          + devfs_stats
.entries 
* sizeof(devdirent_t
) 
 325                          + devfs_stats
.stringspace
 
 327                 fsap
->f_bused 
= fsap
->f_blocks
; 
 328                 VFSATTR_SET_SUPPORTED(fsap
, f_blocks
); 
 329                 VFSATTR_SET_SUPPORTED(fsap
, f_bused
); 
 331         VFSATTR_RETURN(fsap
, f_bfree
, 0); 
 332         VFSATTR_RETURN(fsap
, f_bavail
, 0); 
 333         VFSATTR_RETURN(fsap
, f_files
, devfs_stats
.nodes
); 
 334         VFSATTR_RETURN(fsap
, f_ffree
, 0); 
 335         VFSATTR_RETURN(fsap
, f_fssubtype
, 0); 
 337         if (VFSATTR_IS_ACTIVE(fsap
, f_capabilities
)) { 
 338                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_FORMAT
] = 
 339                         VOL_CAP_FMT_SYMBOLICLINKS 
| 
 340                         VOL_CAP_FMT_HARDLINKS 
| 
 341                         VOL_CAP_FMT_NO_ROOT_TIMES 
| 
 342                         VOL_CAP_FMT_CASE_SENSITIVE 
| 
 343                         VOL_CAP_FMT_CASE_PRESERVING 
| 
 344                         VOL_CAP_FMT_FAST_STATFS 
| 
 345                         VOL_CAP_FMT_2TB_FILESIZE 
| 
 346                         VOL_CAP_FMT_HIDDEN_FILES
; 
 347                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_INTERFACES
] = 
 348                         VOL_CAP_INT_ATTRLIST 
; 
 349                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED1
] = 0; 
 350                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED2
] = 0; 
 352                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_FORMAT
] = 
 353                         VOL_CAP_FMT_PERSISTENTOBJECTIDS 
| 
 354                         VOL_CAP_FMT_SYMBOLICLINKS 
| 
 355                         VOL_CAP_FMT_HARDLINKS 
| 
 356                         VOL_CAP_FMT_JOURNAL 
| 
 357                         VOL_CAP_FMT_JOURNAL_ACTIVE 
| 
 358                         VOL_CAP_FMT_NO_ROOT_TIMES 
| 
 359                         VOL_CAP_FMT_SPARSE_FILES 
| 
 360                         VOL_CAP_FMT_ZERO_RUNS 
| 
 361                         VOL_CAP_FMT_CASE_SENSITIVE 
| 
 362                         VOL_CAP_FMT_CASE_PRESERVING 
| 
 363                         VOL_CAP_FMT_FAST_STATFS 
| 
 364                         VOL_CAP_FMT_2TB_FILESIZE 
| 
 365                         VOL_CAP_FMT_OPENDENYMODES 
| 
 366                         VOL_CAP_FMT_HIDDEN_FILES 
| 
 367                         VOL_CAP_FMT_PATH_FROM_ID 
| 
 368                         VOL_CAP_FMT_NO_VOLUME_SIZES
; 
 369                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_INTERFACES
] = 
 370                         VOL_CAP_INT_SEARCHFS 
| 
 371                         VOL_CAP_INT_ATTRLIST 
| 
 372                         VOL_CAP_INT_NFSEXPORT 
| 
 373                         VOL_CAP_INT_READDIRATTR 
| 
 374                         VOL_CAP_INT_EXCHANGEDATA 
| 
 375                         VOL_CAP_INT_COPYFILE 
| 
 376                         VOL_CAP_INT_ALLOCATE 
| 
 377                         VOL_CAP_INT_VOL_RENAME 
| 
 378                         VOL_CAP_INT_ADVLOCK 
| 
 380                         VOL_CAP_INT_EXTENDED_SECURITY 
| 
 381                         VOL_CAP_INT_USERACCESS 
| 
 382                         VOL_CAP_INT_MANLOCK 
| 
 383                         VOL_CAP_INT_EXTENDED_ATTR 
| 
 384                         VOL_CAP_INT_NAMEDSTREAMS
; 
 385                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED1
] = 0; 
 386                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED2
] = 0; 
 388                 VFSATTR_SET_SUPPORTED(fsap
, f_capabilities
); 
 391         if (VFSATTR_IS_ACTIVE(fsap
, f_attributes
)) { 
 392                 fsap
->f_attributes
.validattr
.commonattr 
= 
 393                         ATTR_CMN_NAME 
| ATTR_CMN_DEVID 
| ATTR_CMN_FSID 
| 
 394                         ATTR_CMN_OBJTYPE 
| ATTR_CMN_OBJTAG 
| ATTR_CMN_OBJID 
| 
 396                         ATTR_CMN_MODTIME 
| ATTR_CMN_CHGTIME 
| ATTR_CMN_ACCTIME 
| 
 397                         ATTR_CMN_OWNERID 
| ATTR_CMN_GRPID 
| ATTR_CMN_ACCESSMASK 
| 
 398                         ATTR_CMN_FLAGS 
| ATTR_CMN_USERACCESS 
| ATTR_CMN_FILEID
; 
 399                 fsap
->f_attributes
.validattr
.volattr 
= 
 400                         ATTR_VOL_FSTYPE 
| ATTR_VOL_SIZE 
| ATTR_VOL_SPACEFREE 
| 
 401                         ATTR_VOL_SPACEAVAIL 
| ATTR_VOL_MINALLOCATION 
| 
 402                         ATTR_VOL_OBJCOUNT 
| ATTR_VOL_MAXOBJCOUNT 
| 
 403                         ATTR_VOL_MOUNTPOINT 
| ATTR_VOL_MOUNTFLAGS 
| 
 404                         ATTR_VOL_MOUNTEDDEVICE 
| ATTR_VOL_CAPABILITIES 
| 
 406                 fsap
->f_attributes
.validattr
.dirattr 
= 
 407                         ATTR_DIR_LINKCOUNT 
| ATTR_DIR_MOUNTSTATUS
; 
 408                 fsap
->f_attributes
.validattr
.fileattr 
= 
 409                         ATTR_FILE_LINKCOUNT 
| ATTR_FILE_TOTALSIZE 
| 
 410                         ATTR_FILE_IOBLOCKSIZE 
| ATTR_FILE_DEVTYPE 
| 
 411                         ATTR_FILE_DATALENGTH
; 
 412                 fsap
->f_attributes
.validattr
.forkattr 
= 0; 
 414                 fsap
->f_attributes
.nativeattr
.commonattr 
= 
 415                         ATTR_CMN_NAME 
| ATTR_CMN_DEVID 
| ATTR_CMN_FSID 
| 
 416                         ATTR_CMN_OBJTYPE 
| ATTR_CMN_OBJTAG 
| ATTR_CMN_OBJID 
| 
 418                         ATTR_CMN_MODTIME 
| ATTR_CMN_CHGTIME 
| ATTR_CMN_ACCTIME 
| 
 419                         ATTR_CMN_OWNERID 
| ATTR_CMN_GRPID 
| ATTR_CMN_ACCESSMASK 
| 
 420                         ATTR_CMN_FLAGS 
| ATTR_CMN_USERACCESS 
| ATTR_CMN_FILEID
; 
 421                 fsap
->f_attributes
.nativeattr
.volattr 
= 
 422                         ATTR_VOL_FSTYPE 
| ATTR_VOL_SIZE 
| ATTR_VOL_SPACEFREE 
| 
 423                         ATTR_VOL_SPACEAVAIL 
| ATTR_VOL_MINALLOCATION 
| 
 424                         ATTR_VOL_OBJCOUNT 
| ATTR_VOL_MAXOBJCOUNT 
| 
 425                         ATTR_VOL_MOUNTPOINT 
| ATTR_VOL_MOUNTFLAGS 
| 
 426                         ATTR_VOL_MOUNTEDDEVICE 
| ATTR_VOL_CAPABILITIES 
| 
 428                 fsap
->f_attributes
.nativeattr
.dirattr 
= 
 429                         ATTR_DIR_MOUNTSTATUS
; 
 430                 fsap
->f_attributes
.nativeattr
.fileattr 
= 
 431                         ATTR_FILE_LINKCOUNT 
| ATTR_FILE_TOTALSIZE 
| 
 432                         ATTR_FILE_IOBLOCKSIZE 
| ATTR_FILE_DEVTYPE 
| 
 433                         ATTR_FILE_DATALENGTH
; 
 434                 fsap
->f_attributes
.nativeattr
.forkattr 
= 0; 
 436                 VFSATTR_SET_SUPPORTED(fsap
, f_attributes
); 
 443 devfs_sync(__unused 
struct mount 
*mp
, __unused 
int waitfor
, __unused vfs_context_t ctx
) 
 450 devfs_vget(__unused 
struct mount 
*mp
, __unused ino64_t ino
, __unused 
struct vnode 
**vpp
, __unused vfs_context_t ctx
) 
 455 /************************************************************* 
 456  * The concept of exporting a kernel generated devfs is stupid 
 457  * So don't handle filehandles 
 461 devfs_fhtovp (__unused 
struct mount 
*mp
, __unused 
int fhlen
, __unused 
unsigned char *fhp
, __unused 
struct vnode 
**vpp
, __unused vfs_context_t ctx
) 
 468 devfs_vptofh (__unused 
struct vnode 
*vp
, __unused 
int *fhlenp
, __unused 
unsigned char *fhp
, __unused vfs_context_t ctx
) 
 474 devfs_sysctl(__unused 
int *name
, __unused u_int namelen
, __unused user_addr_t oldp
,  
 475              __unused 
size_t *oldlenp
, __unused user_addr_t newp
,  
 476              __unused 
size_t newlen
, __unused vfs_context_t ctx
) 
 481 #include <sys/namei.h> 
 484  * Function: devfs_kernel_mount 
 486  *   Mount devfs at the given mount point from within the kernel. 
 489 devfs_kernel_mount(char * mntname
) 
 492         vfs_context_t ctx 
= vfs_context_kernel(); 
 493         char fsname
[] = "devfs"; 
 495         error 
= kernel_mount(fsname
, NULLVP
, NULLVP
, mntname
, NULL
, 0, MNT_DONTBROWSE
, KERNEL_MOUNT_NOAUTH
, ctx
); 
 497                 printf("devfs_kernel_mount: kernel_mount failed: %d\n", error
); 
 504 struct vfsops devfs_vfsops 
= { 
 505         .vfs_mount   
= devfs_mount
, 
 506         .vfs_start   
= devfs_start
, 
 507         .vfs_unmount 
= devfs_unmount
, 
 508         .vfs_root    
= devfs_root
, 
 509         .vfs_getattr 
= devfs_vfs_getattr
, 
 510         .vfs_sync    
= devfs_sync
, 
 511         .vfs_vget    
= devfs_vget
, 
 512         .vfs_fhtovp  
= devfs_fhtovp
, 
 513         .vfs_vptofh  
= devfs_vptofh
, 
 514         .vfs_init    
= devfs_init
, 
 515         .vfs_sysctl  
= devfs_sysctl
, 
 516         // There are other VFS ops that we do not support