4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <auth_attr.h>
27 #include <auth_list.h>
40 #include <bsm/devices.h>
42 #include <tsol/label.h>
45 #include <user_attr.h>
47 #include <sys/mkdev.h>
50 #include <sys/procfs.h>
51 #include <sys/param.h>
52 #include <sys/resource.h>
55 #include <sys/types.h>
60 #include <nss_dbdefs.h>
61 #include <bsm/devalloc.h>
62 #include <libdevinfo.h>
65 extern void print_error(int, char *);
67 #if defined(DEBUG) || defined(lint)
68 #define dprintf(s, a) (void) fprintf(stderr, s, a)
69 #define dperror(s) perror(s)
71 #define dprintf(s, a) 0
75 #define DEV_ERRORED(sbuf) (((sbuf).st_mode & ~S_IFMT) == ALLOC_ERR_MODE)
76 #define DEV_ALLOCATED(sbuf) ((sbuf).st_uid != DA_UID || \
77 !(((sbuf).st_mode & ~S_IFMT) == DEALLOC_MODE || \
80 #define ALLOC_CLEAN "-A"
81 #define DEALLOC_CLEAN "-D"
82 #define DAC_DIR "/etc/security/dev"
83 #define DEVICE_AUTH_SEPARATOR ","
84 #define LOCALDEVICE "/dev/console"
85 #define PROCFS "/proc/"
86 #define SFF_NO_ERROR 0x1
88 #define ALLOC_BY_NONE -1
89 #define CHECK_DRANGE 1
90 #define CHECK_URANGE 2
91 #define CHECK_ZLABEL 3
93 extern void audit_allocate_list(char *);
94 extern void audit_allocate_device(char *);
96 extern int system_labeled
;
97 extern char *newenv
[];
101 char sf_path
[MAXPATHLEN
];
118 static int _dev_file_name(struct state_file
*, devmap_t
*);
119 static int lock_dev(char *, struct stat
*);
120 static int _check_label(devalloc_t
*, char *, uid_t
, int);
121 static int create_znode(char *, struct zone_path
*, devmap_t
*);
122 static int remove_znode(char *, devmap_t
*);
123 static int update_device(char **, char *, int);
126 * checks if the invoking user is local to the device
134 if (stat(LOCALDEVICE
, &statbuf
) == 0 &&
135 statbuf
.st_uid
== uid
)
142 * Checks if the user with the specified uid has the specified authorization
145 _is_authorized(char *auths
, uid_t uid
)
147 char *dcp
, *authlist
, *lasts
;
148 char pw_buf
[NSS_BUFLEN_PASSWD
];
149 struct passwd pw_ent
;
152 * first, the easy cases
154 if (strcmp(auths
, "@") == 0)
156 if (strcmp(auths
, "*") == 0)
157 return (ALLOC_BY_NONE
);
158 if (getpwuid_r(uid
, &pw_ent
, pw_buf
, sizeof (pw_buf
)) == NULL
)
160 if (strpbrk(auths
, DEVICE_AUTH_SEPARATOR
) == NULL
)
161 return (chkauthattr(auths
, pw_ent
.pw_name
));
162 authlist
= strdup(auths
);
163 if (authlist
== NULL
)
166 (dcp
= strtok_r(dcp
, DEVICE_AUTH_SEPARATOR
, &lasts
)) != NULL
;
168 if (chkauthattr(dcp
, pw_ent
.pw_name
))
173 return (dcp
!= NULL
);
177 * Checks if the specified user has authorization for the device
180 _is_dev_authorized(devalloc_t
*da
, uid_t uid
)
183 char *auth_list
, *dcp
, *subauth
= NULL
;
185 auth_list
= da
->da_devauth
;
186 if (auth_list
== NULL
)
188 dcp
= strpbrk(auth_list
, KV_TOKEN_DELIMIT
);
190 return (_is_authorized(auth_list
, uid
));
191 if (_is_local(uid
)) {
192 /* the local authorization is before the separator */
193 ares
= dcp
- auth_list
;
194 subauth
= malloc(ares
+ 1);
197 (void) strlcpy(subauth
, auth_list
, (ares
+ 1));
201 ares
= _is_authorized(auth_list
, uid
);
209 check_devs(devmap_t
*dm
)
214 if (dm
->dmap_devarray
== NULL
)
216 for (file
= dm
->dmap_devarray
; *file
!= NULL
; file
++) {
217 if ((status
= access(*file
, F_OK
)) == -1) {
218 dprintf("Unable to access file %s\n", *file
);
227 print_da_defs(da_defs_t
*da_defs
)
232 if (da_defs
->devopts
== NULL
) {
233 dprintf("No default attributes for %s\n", da_defs
->devtype
);
234 return (DEFATTRSERR
);
236 (void) printf("dev_type=%s\n", da_defs
->devtype
);
237 if (_kva2str(da_defs
->devopts
, optbuf
, sizeof (optbuf
), KV_ASSIGN
,
238 KV_TOKEN_DELIMIT
) == 0) {
239 if (p
= rindex(optbuf
, ':'))
241 (void) printf("\t%s\n", optbuf
);
248 print_dev_attrs(int optflag
, devalloc_t
*da
, devmap_t
*dm
,
249 struct file_info
*fip
)
254 (void) printf("device=%s%s", dm
->dmap_devname
, KV_DELIMITER
);
255 (void) printf("type=%s%s", dm
->dmap_devtype
, KV_DELIMITER
);
256 (void) printf("auths=%s%s",
257 (da
->da_devauth
? da
->da_devauth
: ""), KV_DELIMITER
);
258 (void) printf("clean=%s%s",
259 (da
->da_devexec
? da
->da_devexec
: ""), KV_DELIMITER
);
260 if (da
->da_devopts
!= NULL
) {
261 if (_kva2str(da
->da_devopts
, optbuf
, sizeof (optbuf
),
262 KV_ASSIGN
, KV_TOKEN_DELIMIT
) == 0) {
263 if (p
= rindex(optbuf
, ':'))
265 (void) printf("%s", optbuf
);
268 (void) printf("%s", KV_DELIMITER
);
269 if (optflag
& WINDOWING
) {
270 if ((fip
->fi_message
!= NULL
) &&
271 (strcmp(fip
->fi_message
, DAOPT_CLASS
) == 0))
272 (void) printf("owner=/FREE%s", KV_DELIMITER
);
273 else if (DEV_ERRORED(fip
->fi_stat
))
274 (void) printf("owner=/ERROR%s", KV_DELIMITER
);
275 else if (!DEV_ALLOCATED(fip
->fi_stat
))
276 (void) printf("owner=/FREE%s", KV_DELIMITER
);
278 (void) printf("owner=%u%s", fip
->fi_stat
.st_uid
,
281 (void) printf("files=%s", dm
->dmap_devlist
);
286 print_dev(devmap_t
*dm
)
290 (void) printf(gettext("device: %s "), dm
->dmap_devname
);
291 (void) printf(gettext("type: %s "), dm
->dmap_devtype
);
292 (void) printf(gettext("files:"));
293 file
= dm
->dmap_devarray
;
295 for (; *file
!= NULL
; file
++)
296 (void) printf(" %s", *file
);
303 _list_device(int optflag
, uid_t uid
, devalloc_t
*da
, char *zonename
)
307 int is_authorized
= 0;
309 char file_name
[MAXPATHLEN
];
312 struct state_file sf
;
314 fi
.fi_message
= NULL
;
316 if ((dm
= getdmapnam(da
->da_devname
)) == NULL
) {
318 dprintf("Unable to find %s in the maps database\n",
324 if ((optflag
& CLASS
) &&
325 (!(optflag
& (LISTALL
| LISTFREE
| LISTALLOC
)))) {
326 fi
.fi_message
= DAOPT_CLASS
;
327 if (optflag
& LISTATTRS
)
328 print_dev_attrs(optflag
, da
, dm
, &fi
);
334 if (system_labeled
) {
335 if ((error
= _dev_file_name(&sf
, dm
)) != 0) {
337 dprintf("Unable to find %s device files\n",
344 bytes
= snprintf(file_name
, MAXPATHLEN
, "%s/%s", DAC_DIR
,
349 } else if (bytes
>= MAXPATHLEN
) {
350 dprintf("device name %s is too long.\n",
357 if (stat(fname
, &fi
.fi_stat
) != 0) {
358 dprintf("Unable to stat %s\n", fname
);
363 is_authorized
= _is_dev_authorized(da
, uid
);
364 if (optflag
& LISTFREE
) { /* list_devices -n */
366 * list all free devices
368 if (DEV_ALLOCATED(fi
.fi_stat
)) {
372 if (system_labeled
) {
374 * for this free device, check if -
375 * 1. user has authorization to allocate
376 * 2. the zone label is within the label range of the
379 if (is_authorized
== ALLOC_BY_NONE
) {
382 } else if (is_authorized
== 0) {
386 if (_check_label(da
, zonename
, uid
,
387 CHECK_DRANGE
) != 0) {
392 } else if (optflag
& LISTALLOC
) { /* list_devices -u */
394 * list all allocated devices
396 if (!DEV_ALLOCATED(fi
.fi_stat
)) {
397 error
= DEVNALLOCERR
;
400 if (fi
.fi_stat
.st_uid
!= uid
) {
404 if (system_labeled
) {
406 * check if the zone label equals the label at which
407 * the device is allocated.
409 if (_check_label(da
, zonename
, uid
,
410 CHECK_ZLABEL
) != 0) {
415 } else if (optflag
& LISTALL
) { /* list_devices -l */
417 * list all devices - free and allocated - available
419 if (DEV_ALLOCATED(fi
.fi_stat
)) {
420 if (optflag
& WINDOWING
&&
421 (is_authorized
== ALLOC_BY_NONE
)) {
423 * don't complain if we're here for the GUI.
426 } else if (fi
.fi_stat
.st_uid
!= uid
) {
427 if (!(optflag
& WINDOWING
)) {
432 if (system_labeled
&& !(optflag
& WINDOWING
)) {
434 * if we're not displaying in the GUI,
435 * check if the zone label equals the label
436 * at which the device is allocated.
438 if (_check_label(da
, zonename
, uid
,
439 CHECK_ZLABEL
) != 0) {
444 } else if (system_labeled
&& !(optflag
& WINDOWING
)) {
446 * if we're not displaying in the GUI,
447 * for this free device, check if -
448 * 1. user has authorization to allocate
449 * 2. the zone label is within the label range of the
452 if (is_authorized
== ALLOC_BY_NONE
) {
455 } else if (is_authorized
== 0) {
459 if (_check_label(da
, zonename
, uid
,
460 CHECK_DRANGE
) != 0) {
466 if (system_labeled
&& DEV_ERRORED(fi
.fi_stat
) && !(optflag
& LISTALL
)) {
470 if (check_devs(dm
) == -1) {
474 if (optflag
& LISTATTRS
)
475 print_dev_attrs(optflag
, da
, dm
, &fi
);
488 list_devices(int optflag
, uid_t uid
, char *device
, char *zonename
)
495 if (system_labeled
&& optflag
& WINDOWING
&& !(optflag
& LISTATTRS
)) {
497 * Private interface for GUI.
499 (void) puts(DA_DB_LOCK
);
502 if (optflag
& USERID
) {
504 * we need device.revoke to list someone else's devices
506 if (!_is_authorized(DEVICE_REVOKE_AUTH
, getuid()))
509 if (system_labeled
) {
510 if (!(optflag
& USERID
) &&
511 !_is_authorized(DEFAULT_DEV_ALLOC_AUTH
, uid
))
513 * we need device.allocate to list our devices
516 if (optflag
& LISTDEFS
) {
518 * list default attrs from devalloc_defaults
523 * list default attrs for this device type
525 da_defs
= getdadeftype(device
);
526 if (da_defs
== NULL
) {
528 dprintf("No default attributes for "
530 return (DEFATTRSERR
);
532 error
= print_da_defs(da_defs
);
533 freedadefent(da_defs
);
536 * list everything in devalloc_defaults
538 while ((da_defs
= getdadefent()) != NULL
) {
539 (void) print_da_defs(da_defs
);
540 freedadefent(da_defs
);
548 * Lock the database to make sure no body writes to it while we are
551 (void) lock_dev(NULL
, NULL
);
554 if (optflag
& CLASS
) {
556 * list all devices of this class.
558 while ((da
= getdaent()) != NULL
) {
559 class = kva_match(da
->da_devopts
, DAOPT_CLASS
);
560 if (class && (strcmp(class, device
) == 0)) {
561 (void) _list_device(optflag
, uid
, da
,
570 if ((da
= getdanam(device
)) == NULL
) {
574 error
= _list_device(optflag
, uid
, da
, zonename
);
581 while ((da
= getdaent()) != NULL
) {
582 (void) _list_device(optflag
, uid
, da
, zonename
);
592 * Set the DAC characteristics of the file.
593 * This uses a fancy chmod() by setting a minimal ACL which sets the mode
594 * and discards any existing ACL.
597 _newdac(char *file
, uid_t owner
, gid_t group
, o_mode_t mode
)
601 if (mode
== ALLOC_MODE
) {
602 if (chown(file
, owner
, group
) == -1) {
603 dperror("newdac: unable to chown");
607 if (chown(file
, owner
, group
) == -1) {
608 dperror("newdac: unable to chown");
611 } while (fdetach(file
) == 0);
616 if (strncmp(file
, "/dev/", strlen("/dev/")) != 0) {
618 * This could be a SunRay device that is in /tmp.
620 if (chmod(file
, mode
) == -1) {
621 dperror("newdac: unable to chmod");
625 err
= acl_strip(file
, owner
, group
, (mode_t
)mode
);
629 dperror("newdac: unable to setacl");
638 * locks a section of DA_DB_LOCK.
639 * returns lock fd if successful, else -1 on error.
642 lock_dev(char *file
, struct stat
*statbuf
)
644 static int lockfd
= -1;
653 lockfile
= DA_DB_LOCK
;
658 offset
= statbuf
->st_rdev
;
659 dprintf("locking %s\n", file
);
662 dprintf("locking %s\n", lockfile
);
664 if ((lockfd
== -1) &&
665 (lockfd
= open(lockfile
, O_RDWR
| O_CREAT
, 0600)) == -1) {
666 dperror("lock_dev: cannot open lock file");
669 if (system_labeled
) {
670 (void) _newdac(lockfile
, DA_UID
, DA_GID
, 0600);
671 if (lseek(lockfd
, offset
, SEEK_SET
) == -1) {
672 dperror("lock_dev: cannot position lock file");
680 ret
= lockf(lockfd
, F_TLOCK
, size
);
683 if ((errno
!= EACCES
) && (errno
!= EAGAIN
)) {
684 dperror("lock_dev: cannot set lock");
696 mk_alloc(devmap_t
*list
, uid_t uid
, struct zone_path
*zpath
)
701 gid_t gid
= getgid();
702 mode_t mode
= ALLOC_MODE
;
704 file
= list
->dmap_devarray
;
707 for (; *file
!= NULL
; file
++) {
708 dprintf("Allocating %s\n", *file
);
709 if ((error
= _newdac(*file
, uid
, gid
, mode
)) != 0) {
710 (void) _newdac(*file
, ALLOC_ERRID
, DA_GID
,
715 if (system_labeled
&& zpath
->count
&& (error
== 0)) {
717 * mark as allocated any new device nodes that we
718 * created in local zone
720 for (i
= 0; i
< zpath
->count
; i
++) {
721 dprintf("Allocating %s\n", zpath
->path
[i
]);
722 if ((error
= _newdac(zpath
->path
[i
], uid
, gid
,
724 (void) _newdac(zpath
->path
[i
], ALLOC_ERRID
,
725 DA_GID
, ALLOC_ERR_MODE
);
735 * mk_revoke() is used instead of system("/usr/sbin/fuser -k file")
736 * because "/usr/sbin/fuser -k file" kills all processes
737 * working with the file, even "vold" (bug #4095152).
740 mk_revoke(int optflag
, char *file
)
742 int r
= 0, p
[2], fp
, lock
;
744 char buf
[MAXPATHLEN
];
749 (void) strcpy(buf
, PROCFS
);
751 * vfork() and execl() just to make the same output
752 * as before fixing of bug #4095152.
753 * The problem is that the "fuser" command prints
754 * one part of output into stderr and another into stdout,
755 * but user sees them mixed. Of course, better to change "fuser"
756 * or to intercept and not to print its output.
758 if (!(optflag
& SILENT
)) {
763 dprintf("first exec fuser %s\n", file
);
764 (void) execl("/usr/sbin/fuser", "fuser", file
, NULL
);
765 dperror("first exec fuser");
769 (void) waitpid(c_pid
, &lock
, 0);
770 dprintf("exit status %x\n", lock
);
771 if (WEXITSTATUS(lock
) != 0)
774 dprintf("first continuing c_pid=%d\n", (int)c_pid
);
779 /* vfork() and execl() to catch output and to process it */
782 dperror("second vfork");
785 dprintf("second continuing c_pid=%d\n", (int)c_pid
);
789 (void) fcntl(p
[1], F_DUPFD
, 1);
792 dprintf("second exec fuser %s\n", file
);
793 (void) execl("/usr/sbin/fuser", "fuser", file
, NULL
);
794 dperror("second exec fuser");
798 if ((ptr
= fdopen(p
[0], "r")) != NULL
) {
800 if (fscanf(ptr
, "%d", &fuserpid
) > 0) {
801 (void) sprintf(buf
+ strlen(PROCFS
), "%d",
803 if ((fp
= open(buf
, O_RDONLY
)) == -1) {
807 if (ioctl(fp
, PIOCPSINFO
,
808 (char *)&info
) == -1) {
809 dprintf("%d psinfo failed", fuserpid
);
815 if (strcmp(info
.pr_fname
, "vold") == NULL
) {
816 dprintf("%d matched vold name\n",
820 if (strcmp(info
.pr_fname
, "deallocate")
822 dprintf("%d matched deallocate name\n",
826 dprintf("killing %s", info
.pr_fname
);
827 dprintf("(%d)\n", fuserpid
);
829 kill((pid_t
)fuserpid
, SIGKILL
)) == -1) {
830 dprintf("kill %d", fuserpid
);
837 dperror("fdopen(p[0], r)");
846 mk_unalloc(int optflag
, devmap_t
*list
)
852 audit_allocate_list(list
->dmap_devlist
);
853 file
= list
->dmap_devarray
;
856 for (; *file
!= NULL
; file
++) {
857 dprintf("Deallocating %s\n", *file
);
858 if (mk_revoke(optflag
, *file
) < 0) {
859 dprintf("mk_unalloc: unable to revoke %s\n", *file
);
863 status
= _newdac(*file
, DA_UID
, DA_GID
, DEALLOC_MODE
);
873 mk_error(devmap_t
*list
)
878 audit_allocate_list(list
->dmap_devlist
);
879 file
= list
->dmap_devarray
;
882 for (; *file
!= NULL
; file
++) {
883 dprintf("Putting %s in error state\n", *file
);
884 status
= _newdac(*file
, ALLOC_ERRID
, DA_GID
, ALLOC_ERR_MODE
);
891 exec_clean(int optflag
, char *devname
, char *path
, uid_t uid
, char *zonename
,
895 int status
= 0, exit_status
;
896 char *mode
, *cmd
, *wdwcmd
, *zoneroot
;
897 char *devzone
= zonename
;
898 char wdwpath
[PATH_MAX
];
899 char zonepath
[MAXPATHLEN
];
901 char pw_buf
[NSS_BUFLEN_PASSWD
];
902 struct passwd pw_ent
;
905 if (system_labeled
) {
906 if ((zoneroot
= getzonerootbyname(zonename
)) == NULL
) {
907 if (strcmp(clean_arg
, ALLOC_CLEAN
) == 0) {
909 } else if (optflag
& FORCE
) {
910 (void) strcpy(zonepath
, "/");
911 devzone
= GLOBAL_ZONENAME
;
913 dprintf("unable to get label for %s zone\n",
918 (void) strcpy(zonepath
, zoneroot
);
922 if (getpwuid_r(uid
, &pw_ent
, pw_buf
, sizeof (pw_buf
)) == NULL
)
924 if (optflag
& FORCE_ALL
)
926 else if (optflag
& FORCE
)
932 if ((cmd
= strrchr(path
, '/')) == NULL
)
935 cmd
++; /* skip leading '/' */
942 if (system_labeled
&& (optflag
& WINDOWING
)) {
943 /* First try .windowing version of script */
944 (void) strncpy(wdwpath
, path
, PATH_MAX
);
945 (void) strncat(wdwpath
, ".windowing", PATH_MAX
);
946 if ((wdwcmd
= strrchr(wdwpath
, '/')) == NULL
)
948 (void) execl(wdwpath
, wdwcmd
, mode
, devname
, clean_arg
,
949 pw_ent
.pw_name
, devzone
, zonepath
, NULL
);
950 /* If that failed, run regular version via dtterm */
951 (void) snprintf(title
, sizeof (title
),
953 strcmp(clean_arg
, ALLOC_CLEAN
) == 0 ?
954 "allocation" : "deallocation", devname
);
955 (void) execl("/usr/dt/bin/dtterm", "dtterm",
956 "-title", title
, "-geometry", "x10+100+400",
957 "-e", "/etc/security/lib/wdwwrapper",
958 path
, mode
, devname
, clean_arg
, pw_ent
.pw_name
,
959 devzone
, zonepath
, NULL
);
961 * And if that failed, continue on to try
962 * running regular version directly.
965 dprintf("clean script: %s, ", path
);
966 dprintf("cmd=%s, ", cmd
);
967 dprintf("mode=%s, ", mode
);
968 if (system_labeled
) {
969 dprintf("devname=%s ", devname
);
970 dprintf("zonename=%s ", devzone
);
971 dprintf("zonepath=%s ", zonepath
);
972 dprintf("username=%s\n", pw_ent
.pw_name
);
973 (void) execl(path
, cmd
, mode
, devname
, clean_arg
,
974 pw_ent
.pw_name
, devzone
, zonepath
, NULL
);
976 dprintf("devname=%s\n", devname
);
977 (void) execle(path
, cmd
, mode
, devname
, NULL
, newenv
);
979 dprintf("Unable to execute clean up script %s\n", path
);
983 (void) waitpid(c
, &status
, 0);
984 dprintf("Child %d", c
);
985 if (WIFEXITED(status
)) {
986 exit_status
= WEXITSTATUS(status
);
987 dprintf(" exited, status: %d\n", exit_status
);
988 return (exit_status
);
989 } else if (WIFSIGNALED(status
)) {
990 dprintf(" killed, signal %d\n", WTERMSIG(status
));
992 dprintf(": exit status %d\n", status
);
999 _deallocate_dev(int optflag
, devalloc_t
*da
, devmap_t
*dm_in
, uid_t uid
,
1000 char *zonename
, int *lock_fd
)
1004 int is_authorized
= 0;
1007 char file_name
[MAXPATHLEN
];
1008 char *devzone
= NULL
;
1009 devmap_t
*dm
= NULL
, *dm_new
= NULL
;
1010 struct stat stat_buf
;
1011 struct state_file sf
;
1013 if (dm_in
== NULL
) {
1015 if ((dm_new
= getdmapnam(da
->da_devname
)) == NULL
) {
1017 dprintf("Unable to find %s in device map database\n",
1026 if (system_labeled
) {
1027 if (_dev_file_name(&sf
, dm
) != 0) {
1029 freedmapent(dm_new
);
1030 dprintf("Unable to find %s device files\n",
1037 bytes
= snprintf(file_name
, MAXPATHLEN
, "%s/%s", DAC_DIR
,
1042 } else if (bytes
>= MAXPATHLEN
) {
1043 dprintf("device name %s is too long.\n",
1051 audit_allocate_device(fname
);
1053 if (stat(fname
, &stat_buf
) != 0) {
1054 dprintf("Unable to stat %s\n", fname
);
1058 is_authorized
= _is_dev_authorized(da
, uid
);
1059 if (is_authorized
== ALLOC_BY_NONE
) {
1060 dprintf("Not deallocating %s, not allocatable\n",
1064 if (!(optflag
& (FORCE
| FORCE_ALL
)) && !is_authorized
) {
1065 dprintf("User %d is unauthorized to deallocate\n", (int)uid
);
1069 if (system_labeled
) {
1071 * unless we're here to deallocate by force, check if the
1072 * label at which the device is currently allocated is
1073 * within the user label range.
1075 if (!(optflag
& FORCE
) &&
1076 _check_label(da
, zonename
, uid
, CHECK_URANGE
) != 0) {
1077 error
= LABELRNGERR
;
1081 if (!(optflag
& FORCE
) && stat_buf
.st_uid
!= uid
&&
1082 DEV_ALLOCATED(stat_buf
)) {
1086 if (!DEV_ALLOCATED(stat_buf
)) {
1087 if (DEV_ERRORED(stat_buf
)) {
1088 if (!(optflag
& FORCE
)) {
1089 error
= DEVSTATEERR
;
1093 error
= DEVNALLOCERR
;
1097 /* All checks passed, time to lock and deallocate */
1098 if ((*lock_fd
= lock_dev(fname
, &stat_buf
)) == -1) {
1102 if (system_labeled
) {
1103 devzone
= kva_match(da
->da_devopts
, DAOPT_ZONE
);
1104 if (devzone
== NULL
) {
1105 devzone
= GLOBAL_ZONENAME
;
1106 } else if (strcmp(devzone
, GLOBAL_ZONENAME
) != 0) {
1107 if ((remove_znode(devzone
, dm
) != 0) &&
1108 !(optflag
& FORCE
)) {
1114 if ((error
= mk_unalloc(optflag
, dm
)) != 0) {
1115 if (!(optflag
& FORCE
))
1118 if (system_labeled
== 0) {
1119 if ((error
= _newdac(fname
, DA_UID
, DA_GID
,
1120 DEALLOC_MODE
)) != 0) {
1121 (void) _newdac(file_name
, DA_UID
, DA_GID
,
1127 * if we are deallocating device owned by someone else,
1128 * pass the owner's uid to the cleaning script.
1130 nuid
= (stat_buf
.st_uid
== uid
) ? uid
: stat_buf
.st_uid
;
1131 error
= exec_clean(optflag
, da
->da_devname
, da
->da_devexec
, nuid
,
1132 devzone
, DEALLOC_CLEAN
);
1134 if (!(optflag
& (FORCE
| FORCE_ALL
))) {
1136 (void) mk_error(dm
);
1144 freedmapent(dm_new
);
1149 _allocate_dev(int optflag
, uid_t uid
, devalloc_t
*da
, char *zonename
,
1155 int is_authorized
= 0;
1156 int dealloc_optflag
= 0;
1158 char file_name
[MAXPATHLEN
];
1160 struct stat stat_buf
;
1161 struct state_file sf
;
1162 struct zone_path zpath
;
1167 if ((dm
= getdmapnam(da
->da_devname
)) == NULL
) {
1169 dprintf("Unable to find %s in device map database\n",
1174 if (system_labeled
) {
1175 if (_dev_file_name(&sf
, dm
) != 0) {
1177 dprintf("Unable to find %s device files\n",
1184 bytes
= snprintf(file_name
, MAXPATHLEN
, "%s/%s", DAC_DIR
,
1189 } else if (bytes
>= MAXPATHLEN
) {
1190 dprintf("device name %s is too long.\n",
1198 (void) audit_allocate_device(fname
);
1200 if (stat(fname
, &stat_buf
) != 0) {
1201 dprintf("Unable to stat %s\n", fname
);
1206 if (DEV_ERRORED(stat_buf
)) {
1207 error
= DEVSTATEERR
;
1210 is_authorized
= _is_dev_authorized(da
, uid
);
1211 if (is_authorized
== ALLOC_BY_NONE
) {
1212 dprintf("Device %s is not allocatable\n", da
->da_devname
);
1215 } else if (!is_authorized
&& !(optflag
& USERNAME
)) {
1216 dprintf("User %d is unauthorized to allocate\n", (int)uid
);
1220 if (system_labeled
) {
1222 * check if label of the zone to which the device is being
1223 * allocated is within the device label range.
1225 if (_check_label(da
, zonename
, uid
, CHECK_DRANGE
) != 0) {
1226 error
= LABELRNGERR
;
1230 if (check_devs(dm
) == -1) {
1234 if (DEV_ALLOCATED(stat_buf
)) {
1235 if (optflag
& FORCE
) {
1236 if (optflag
& SILENT
)
1237 dealloc_optflag
= FORCE
|SILENT
;
1239 dealloc_optflag
= FORCE
;
1240 if (_deallocate_dev(dealloc_optflag
, da
, dm
, uid
,
1241 zonename
, lock_fd
)) {
1242 dprintf("Couldn't force deallocate device %s\n",
1247 } else if (stat_buf
.st_uid
== uid
) {
1248 error
= PREALLOCERR
;
1255 /* All checks passed, time to lock and allocate */
1256 if ((*lock_fd
= lock_dev(fname
, &stat_buf
)) == -1) {
1260 if (system_labeled
) {
1262 * Run the cleaning program; it also mounts allocated
1263 * device if required.
1265 error
= exec_clean(optflag
, da
->da_devname
, da
->da_devexec
, uid
,
1266 zonename
, ALLOC_CLEAN
);
1267 if (error
!= DEVCLEAN_OK
) {
1269 case DEVCLEAN_ERROR
:
1270 case DEVCLEAN_SYSERR
:
1271 dprintf("allocate: "
1272 "Error in device clean program %s\n",
1275 (void) mk_error(dm
);
1277 case DEVCLEAN_BADMOUNT
:
1278 dprintf("allocate: Failed to mount device %s\n",
1281 case DEVCLEAN_MOUNTOK
:
1289 * If not mounted, create zonelinks, if this is not the
1292 if ((strcmp(zonename
, GLOBAL_ZONENAME
) != 0) &&
1293 (error
!= DEVCLEAN_MOUNTOK
)) {
1294 if (create_znode(zonename
, &zpath
, dm
) != 0) {
1301 (void) audit_allocate_list(dm
->dmap_devlist
);
1303 if ((error
= mk_alloc(dm
, uid
, &zpath
)) != 0) {
1304 (void) mk_unalloc(optflag
, dm
);
1308 if (system_labeled
== 0) {
1309 if ((error
= _newdac(file_name
, uid
, getgid(),
1310 ALLOC_MODE
)) != 0) {
1311 (void) _newdac(file_name
, DA_UID
, DA_GID
,
1319 for (i
= 0; i
< zpath
.count
; i
++)
1320 free(zpath
.path
[i
]);
1328 _store_devnames(int *count
, struct dev_names
*dnms
, char *zonename
,
1329 devalloc_t
*da
, int flag
)
1333 dnms
->dnames
= (char **)realloc(dnms
->dnames
,
1334 (*count
+ 1) * sizeof (char *));
1336 dnms
->dnames
[*count
] = strdup(da
->da_devname
);
1339 dnms
->dnames
[*count
] = NULL
;
1340 if (flag
== DA_ADD_ZONE
)
1341 (void) update_device(dnms
->dnames
, zonename
,
1343 else if (flag
== DA_REMOVE_ZONE
)
1344 (void) update_device(dnms
->dnames
, NULL
,
1346 for (i
= 0; i
< *count
; i
++)
1347 free(dnms
->dnames
[i
]);
1353 allocate(int optflag
, uid_t uid
, char *device
, char *zonename
)
1359 struct dev_names dnms
;
1361 if (optflag
& (FORCE
| USERID
| USERNAME
)) {
1362 if (!_is_authorized(DEVICE_REVOKE_AUTH
, getuid()))
1367 if (optflag
& TYPE
) {
1369 * allocate devices of this type
1371 while ((da
= getdatype(device
)) != NULL
) {
1372 if (system_labeled
&&
1373 da_check_logindevperm(da
->da_devname
)) {
1377 dprintf("trying to allocate %s\n", da
->da_devname
);
1378 error
= _allocate_dev(optflag
, uid
, da
, zonename
,
1380 if (system_labeled
&& (error
== 0)) {
1382 * we need to record in device_allocate the
1383 * label (zone name) at which this device is
1384 * being allocated. store this device entry.
1386 _store_devnames(&count
, &dnms
, zonename
, da
, 0);
1393 * allocate this device
1395 if ((da
= getdanam(device
)) == NULL
) {
1399 if (system_labeled
&& da_check_logindevperm(device
)) {
1401 return (LOGINDEVPERMERR
);
1403 dprintf("trying to allocate %s\n", da
->da_devname
);
1404 error
= _allocate_dev(optflag
, uid
, da
, zonename
, &lock_fd
);
1406 * we need to record in device_allocate the label (zone name)
1407 * at which this device is being allocated. store this device
1410 if (system_labeled
&& (error
== 0))
1411 _store_devnames(&count
, &dnms
, zonename
, da
, 0);
1413 if (error
== DEVCLEAN_BADMOUNT
)
1418 (void) close(lock_fd
);
1420 * add to device_allocate labels (zone names) for the devices we
1424 _store_devnames(&count
, &dnms
, zonename
, NULL
, DA_ADD_ZONE
);
1431 deallocate(int optflag
, uid_t uid
, char *device
, char *zonename
)
1438 struct dev_names dnms
;
1440 if (optflag
& (FORCE
| FORCE_ALL
)) {
1441 if (!_is_authorized(DEVICE_REVOKE_AUTH
, getuid()))
1444 if (optflag
& FORCE_ALL
)
1448 if (optflag
& FORCE_ALL
) {
1450 * deallocate all devices
1452 while ((da
= getdaent()) != NULL
) {
1453 if (system_labeled
&&
1454 da_check_logindevperm(da
->da_devname
)) {
1458 dprintf("trying to deallocate %s\n", da
->da_devname
);
1459 error
= _deallocate_dev(optflag
, da
, NULL
, uid
,
1460 zonename
, &lock_fd
);
1461 if (system_labeled
&& (error
== 0)) {
1463 * we need to remove this device's allocation
1464 * label (zone name) from device_allocate.
1465 * store this device name.
1467 _store_devnames(&count
, &dnms
, zonename
, da
, 0);
1472 } else if (system_labeled
&& (optflag
& TYPE
)) {
1474 * deallocate all devices of this type
1476 while ((da
= getdatype(device
)) != NULL
) {
1477 if (da_check_logindevperm(da
->da_devname
)) {
1481 dprintf("trying to deallocate %s\n", da
->da_devname
);
1482 error
= _deallocate_dev(optflag
, da
, NULL
, uid
,
1483 zonename
, &lock_fd
);
1486 * we need to remove this device's allocation
1487 * label (zone name) from device_allocate.
1488 * store this device name.
1490 _store_devnames(&count
, &dnms
, zonename
, da
, 0);
1495 } else if (system_labeled
&& (optflag
& CLASS
)) {
1497 * deallocate all devices of this class (for sunray)
1499 while ((da
= getdaent()) != NULL
) {
1500 class = kva_match(da
->da_devopts
, DAOPT_CLASS
);
1501 if (class && (strcmp(class, device
) == 0)) {
1502 dprintf("trying to deallocate %s\n",
1504 error
= _deallocate_dev(optflag
, da
, NULL
, uid
,
1505 zonename
, &lock_fd
);
1508 * we need to remove this device's
1509 * allocation label (zone name) from
1510 * device_allocate. store this device
1513 _store_devnames(&count
, &dnms
, zonename
,
1520 } else if (!(optflag
& TYPE
)) {
1522 * deallocate this device
1524 if ((da
= getdanam(device
)) == NULL
) {
1528 if (system_labeled
&& da_check_logindevperm(da
->da_devname
)) {
1530 return (LOGINDEVPERMERR
);
1532 dprintf("trying to deallocate %s\n", da
->da_devname
);
1533 error
= _deallocate_dev(optflag
, da
, NULL
, uid
, zonename
,
1535 if (system_labeled
&& (error
== 0)) {
1537 * we need to remove this device's allocation label
1538 * (zone name) from device_allocate. store this
1541 _store_devnames(&count
, &dnms
, zonename
, da
, 0);
1544 if (error
== DEVCLEAN_BADMOUNT
)
1549 (void) close(lock_fd
);
1551 * remove from device_allocate labels (zone names) for the devices we
1555 _store_devnames(&count
, &dnms
, zonename
, NULL
, DA_REMOVE_ZONE
);
1561 _dev_file_name(struct state_file
*sfp
, devmap_t
*dm
)
1564 /* if devlist is generated, never leave device in error state */
1565 if (dm
->dmap_devlist
[0] == '`')
1566 sfp
->sf_flags
|= SFF_NO_ERROR
;
1567 if (dm
->dmap_devarray
== NULL
||
1568 dm
->dmap_devarray
[0] == NULL
)
1570 (void) strncpy(sfp
->sf_path
, dm
->dmap_devarray
[0],
1571 sizeof (sfp
->sf_path
));
1572 sfp
->sf_path
[sizeof (sfp
->sf_path
) - 1] = '\0';
1573 if (sfp
->sf_path
[0] == '\0') {
1574 dprintf("dev_file_name: no device list for %s\n",
1584 * checks the device label range against zone label, which is also
1585 * user's current label.
1586 * returns 0 if in range, -1 for all other conditions.
1591 _check_label(devalloc_t
*da
, char *zonename
, uid_t uid
, int flag
)
1595 char *alloczone
, *lstr
;
1596 char pw_buf
[NSS_BUFLEN_PASSWD
];
1599 struct passwd pw_ent
;
1601 if ((da
== NULL
) || (zonename
== NULL
))
1604 if ((zlabel
= getzonelabelbyname(zonename
)) == NULL
) {
1605 dprintf("unable to get label for %s zone\n", zonename
);
1608 if (flag
== CHECK_DRANGE
) {
1611 drange
.lower_bound
= blabel_alloc();
1612 lstr
= kva_match(da
->da_devopts
, DAOPT_MINLABEL
);
1614 bsllow(drange
.lower_bound
);
1615 } else if (stobsl(lstr
, drange
.lower_bound
, NO_CORRECTION
,
1617 dprintf("bad min_label for device %s\n",
1620 blabel_free(drange
.lower_bound
);
1623 drange
.upper_bound
= blabel_alloc();
1624 lstr
= kva_match(da
->da_devopts
, DAOPT_MAXLABEL
);
1626 bslhigh(drange
.upper_bound
);
1627 } else if (stobsl(lstr
, drange
.upper_bound
, NO_CORRECTION
,
1629 dprintf("bad max_label for device %s\n",
1632 blabel_free(drange
.lower_bound
);
1633 blabel_free(drange
.upper_bound
);
1636 if (blinrange(zlabel
, &drange
) == 0) {
1637 char *zlbl
= NULL
, *min
= NULL
, *max
= NULL
;
1639 (void) bsltos(zlabel
, &zlbl
, 0, 0);
1640 (void) bsltos(drange
.lower_bound
, &min
, 0, 0);
1641 (void) bsltos(drange
.upper_bound
, &max
, 0, 0);
1642 dprintf("%s zone label ", zonename
);
1643 dprintf("%s outside device label range: ", zlbl
);
1644 dprintf("min - %s, ", min
);
1645 dprintf("max - %s\n", max
);
1647 blabel_free(drange
.lower_bound
);
1648 blabel_free(drange
.upper_bound
);
1651 } else if (flag
== CHECK_URANGE
) {
1652 if (getpwuid_r(uid
, &pw_ent
, pw_buf
, sizeof (pw_buf
)) == NULL
) {
1653 dprintf("Unable to get passwd entry for userid %d\n",
1658 if ((range
= getuserrange(pw_ent
.pw_name
)) == NULL
) {
1659 dprintf("Unable to get label range for userid %d\n",
1664 in_range
= blinrange(zlabel
, range
);
1666 blabel_free(range
->lower_bound
);
1667 blabel_free(range
->upper_bound
);
1669 if (in_range
== 0) {
1670 dprintf("%s device label ", da
->da_devname
);
1671 dprintf("out of user %d label range\n", (int)uid
);
1674 } else if (flag
== CHECK_ZLABEL
) {
1675 alloczone
= kva_match(da
->da_devopts
, DAOPT_ZONE
);
1676 if (alloczone
== NULL
) {
1680 if (strcmp(zonename
, alloczone
) != 0) {
1681 dprintf("%s zone is different than ", zonename
);
1682 dprintf("%s zone to which the device ", alloczone
);
1683 dprintf("%s is allocated\n", da
->da_devname
);
1694 create_znode(char *zonename
, struct zone_path
*zpath
, devmap_t
*list
)
1699 char *p
, *tmpfile
, *zoneroot
;
1701 char zonepath
[MAXPATHLEN
];
1702 di_prof_t prof
= NULL
;
1704 file
= list
->dmap_devarray
;
1707 if ((zoneroot
= getzonerootbyname(zonename
)) == NULL
) {
1708 dprintf("unable to get label for %s zone\n", zonename
);
1711 (void) strcpy(zonepath
, zoneroot
);
1713 len
= strlen(zonepath
);
1714 size
= sizeof (zonepath
);
1715 (void) strlcat(zonepath
, "/dev", size
);
1716 if (di_prof_init(zonepath
, &prof
)) {
1717 dprintf("failed to initialize dev profile at %s\n", zonepath
);
1720 zonepath
[len
] = '\0';
1721 for (; *file
!= NULL
; file
++) {
1723 * First time initialization
1725 tmpfile
= strdup(*file
);
1728 * Most devices have pathnames starting in /dev
1729 * but SunRay devices do not. In SRRS 3.1 they use /tmp.
1731 * If the device pathname is not in /dev then create
1732 * a symbolic link to it and put the device in /dev
1734 if (strncmp(tmpfile
, "/dev/", strlen("/dev/")) != 0) {
1736 char srclinkdir
[MAXPATHLEN
];
1737 char dstlinkdir
[MAXPATHLEN
];
1739 linkdir
= strchr(tmpfile
+ 1, '/');
1740 p
= strchr(linkdir
+ 1, '/');
1742 (void) strcpy(dstlinkdir
, "/dev");
1743 (void) strncat(dstlinkdir
, linkdir
, MAXPATHLEN
);
1744 (void) snprintf(srclinkdir
, MAXPATHLEN
, "%s/root%s",
1746 (void) symlink(dstlinkdir
, srclinkdir
);
1748 (void) strncat(dstlinkdir
, p
, MAXPATHLEN
);
1750 tmpfile
= strdup(dstlinkdir
);
1752 if (di_prof_add_dev(prof
, tmpfile
)) {
1753 dprintf("failed to add %s to profile\n", tmpfile
);
1757 if (strlcat(zonepath
, tmpfile
, size
) >= size
) {
1758 dprintf("Buffer overflow in create_znode for %s\n",
1766 if ((zpath
->path
= (char **)realloc(zpath
->path
,
1767 (fcount
* sizeof (char *)))) == NULL
) {
1771 zpath
->path
[zpath
->count
] = strdup(zonepath
);
1772 zpath
->count
= fcount
;
1773 zonepath
[len
] = '\0';
1776 if (di_prof_commit(prof
))
1777 dprintf("failed to add devices to zone %s\n", zonename
);
1784 remove_znode(char *zonename
, devmap_t
*dm
)
1789 char zonepath
[MAXPATHLEN
];
1790 di_prof_t prof
= NULL
;
1792 file
= dm
->dmap_devarray
;
1795 if ((zoneroot
= getzonerootbyname(zonename
)) == NULL
) {
1796 (void) snprintf(zonepath
, MAXPATHLEN
, "/zone/%s", zonename
);
1798 (void) strcpy(zonepath
, zoneroot
);
1802 * To support SunRay we will just deal with the
1803 * file in /dev, not the symlinks.
1805 (void) strncat(zonepath
, "/dev", MAXPATHLEN
);
1806 len
= strlen(zonepath
);
1807 if (di_prof_init(zonepath
, &prof
)) {
1808 dprintf("failed to initialize dev profile at %s\n", zonepath
);
1811 for (; *file
!= NULL
; file
++) {
1815 * remove device node from zone.
1817 * SunRay devices don't start with /dev
1818 * so skip over first directory to make
1819 * sure it is /dev. SunRay devices in zones
1820 * will have a symlink into /dev but
1821 * we don't ever delete it.
1823 devrelpath
= strchr(*file
+ 1, '/');
1825 if (di_prof_add_exclude(prof
, devrelpath
+ 1)) {
1826 dprintf("Failed exclude %s in dev profile\n", *file
);
1830 zonepath
[len
] = '\0';
1833 if (di_prof_commit(prof
))
1834 dprintf("failed to remove devices from zone %s\n", zonename
);
1840 update_device(char **devnames
, char *zonename
, int flag
)
1843 char *optstr
= NULL
;
1847 dargs
.optflag
= flag
;
1848 dargs
.optflag
|= DA_UPDATE
|DA_ALLOC_ONLY
;
1849 dargs
.rootdir
= NULL
;
1850 dargs
.devnames
= devnames
;
1851 devinfo
.devname
= devinfo
.devtype
= devinfo
.devauths
= devinfo
.devexec
=
1852 devinfo
.devlist
= NULL
;
1853 if (dargs
.optflag
& DA_ADD_ZONE
) {
1854 len
= strlen(DAOPT_ZONE
) + strlen(zonename
) + 3;
1855 if ((optstr
= (char *)malloc(len
)) == NULL
)
1857 (void) snprintf(optstr
, len
, "%s%s%s", DAOPT_ZONE
, KV_ASSIGN
,
1859 devinfo
.devopts
= optstr
;
1861 dargs
.devinfo
= &devinfo
;
1863 rc
= da_update_device(&dargs
);