1*2912Sartem /*************************************************************************** 2*2912Sartem * CVSID: $Id: hal-storage-mount.c,v 1.7 2006/06/21 00:44:03 david Exp $ 3*2912Sartem * 4*2912Sartem * hal-storage-mount.c : Mount wrapper 5*2912Sartem * 6*2912Sartem * Copyright (C) 2006 David Zeuthen, <david@fubar.dk> 7*2912Sartem * 8*2912Sartem * This program is free software; you can redistribute it and/or modify 9*2912Sartem * it under the terms of the GNU General Public License as published by 10*2912Sartem * the Free Software Foundation; either version 2 of the License, or 11*2912Sartem * (at your option) any later version. 12*2912Sartem * 13*2912Sartem * This program is distributed in the hope that it will be useful, 14*2912Sartem * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*2912Sartem * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*2912Sartem * GNU General Public License for more details. 17*2912Sartem * 18*2912Sartem * You should have received a copy of the GNU General Public License 19*2912Sartem * along with this program; if not, write to the Free Software 20*2912Sartem * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21*2912Sartem * 22*2912Sartem **************************************************************************/ 23*2912Sartem 24*2912Sartem 25*2912Sartem #ifdef HAVE_CONFIG_H 26*2912Sartem # include <config.h> 27*2912Sartem #endif 28*2912Sartem 29*2912Sartem #include <stdio.h> 30*2912Sartem #include <stdlib.h> 31*2912Sartem #include <string.h> 32*2912Sartem #include <glib.h> 33*2912Sartem #include <glib/gstdio.h> 34*2912Sartem #ifdef __FreeBSD__ 35*2912Sartem #include <fstab.h> 36*2912Sartem #include <sys/param.h> 37*2912Sartem #include <sys/ucred.h> 38*2912Sartem #include <sys/mount.h> 39*2912Sartem #include <limits.h> 40*2912Sartem #include <pwd.h> 41*2912Sartem #elif sun 42*2912Sartem #include <fcntl.h> 43*2912Sartem #include <sys/mnttab.h> 44*2912Sartem #include <sys/vfstab.h> 45*2912Sartem #include <sys/stat.h> 46*2912Sartem #include <sys/wait.h> 47*2912Sartem #include <bsm/adt.h> 48*2912Sartem #include <bsm/adt_event.h> 49*2912Sartem #else 50*2912Sartem #include <mntent.h> 51*2912Sartem #endif 52*2912Sartem #include <sys/types.h> 53*2912Sartem #include <unistd.h> 54*2912Sartem #include <sys/file.h> 55*2912Sartem #include <errno.h> 56*2912Sartem #include <syslog.h> 57*2912Sartem 58*2912Sartem #include "hal-storage-shared.h" 59*2912Sartem 60*2912Sartem #ifdef __FreeBSD__ 61*2912Sartem struct mtab_handle 62*2912Sartem { 63*2912Sartem struct statfs *mounts; 64*2912Sartem int n_mounts; 65*2912Sartem int iter; 66*2912Sartem }; 67*2912Sartem #endif 68*2912Sartem 69*2912Sartem 70*2912Sartem gboolean 71*2912Sartem mtab_open (gpointer *handle) 72*2912Sartem { 73*2912Sartem #ifdef __FreeBSD__ 74*2912Sartem struct mtab_handle *mtab; 75*2912Sartem 76*2912Sartem mtab = g_new0 (struct mtab_handle, 1); 77*2912Sartem mtab->n_mounts = getmntinfo (&mtab->mounts, MNT_NOWAIT); 78*2912Sartem if (mtab->n_mounts == 0) { 79*2912Sartem g_free (mtab); 80*2912Sartem return FALSE; 81*2912Sartem } 82*2912Sartem 83*2912Sartem *handle = mtab; 84*2912Sartem return TRUE; 85*2912Sartem #elif sun 86*2912Sartem *handle = fopen (MNTTAB, "r"); 87*2912Sartem return *handle != NULL; 88*2912Sartem #else 89*2912Sartem *handle = fopen ("/proc/mounts", "r"); 90*2912Sartem return *handle != NULL; 91*2912Sartem #endif 92*2912Sartem } 93*2912Sartem 94*2912Sartem char * 95*2912Sartem mtab_next (gpointer handle, char **mount_point) 96*2912Sartem { 97*2912Sartem #ifdef __FreeBSD__ 98*2912Sartem struct mtab_handle *mtab = handle; 99*2912Sartem 100*2912Sartem if (mtab->iter < mtab->n_mounts) 101*2912Sartem return mtab->mounts[mtab->iter++].f_mntfromname; 102*2912Sartem else 103*2912Sartem return NULL; 104*2912Sartem #error TODO: set *mount_point to g_strdup()-ed value if mount_point!=NULL 105*2912Sartem #elif sun 106*2912Sartem static struct mnttab mnt; 107*2912Sartem 108*2912Sartem if (getmntent (handle, &mnt) == 0) { 109*2912Sartem if (mount_point != NULL) { 110*2912Sartem *mount_point = g_strdup (mnt.mnt_mountp); 111*2912Sartem } 112*2912Sartem return mnt.mnt_special; 113*2912Sartem } else { 114*2912Sartem return NULL; 115*2912Sartem } 116*2912Sartem #else 117*2912Sartem struct mntent *mnt; 118*2912Sartem 119*2912Sartem mnt = getmntent (handle); 120*2912Sartem 121*2912Sartem if (mnt != NULL) { 122*2912Sartem if (mount_point != NULL) { 123*2912Sartem *mount_point = g_strdup (mnt->mnt_dir); 124*2912Sartem } 125*2912Sartem return mnt->mnt_fsname; 126*2912Sartem } else { 127*2912Sartem return NULL; 128*2912Sartem } 129*2912Sartem #endif 130*2912Sartem } 131*2912Sartem 132*2912Sartem void 133*2912Sartem mtab_close (gpointer handle) 134*2912Sartem { 135*2912Sartem #ifdef __FreeBSD__ 136*2912Sartem g_free (handle); 137*2912Sartem #else 138*2912Sartem fclose (handle); 139*2912Sartem #endif 140*2912Sartem } 141*2912Sartem 142*2912Sartem 143*2912Sartem 144*2912Sartem gboolean 145*2912Sartem fstab_open (gpointer *handle) 146*2912Sartem { 147*2912Sartem #ifdef __FreeBSD__ 148*2912Sartem return setfsent () == 1; 149*2912Sartem #elif sun 150*2912Sartem *handle = fopen (VFSTAB, "r"); 151*2912Sartem return *handle != NULL; 152*2912Sartem #else 153*2912Sartem *handle = fopen ("/etc/fstab", "r"); 154*2912Sartem return *handle != NULL; 155*2912Sartem #endif 156*2912Sartem } 157*2912Sartem 158*2912Sartem char * 159*2912Sartem fstab_next (gpointer handle, char **mount_point) 160*2912Sartem { 161*2912Sartem #ifdef __FreeBSD__ 162*2912Sartem struct fstab *fstab; 163*2912Sartem 164*2912Sartem fstab = getfsent (); 165*2912Sartem 166*2912Sartem /* TODO: fill out mount_point */ 167*2912Sartem if (mount_point != NULL && fstab != NULL) { 168*2912Sartem *mount_point = fstab->fs_file; 169*2912Sartem } 170*2912Sartem 171*2912Sartem return fstab ? fstab->fs_spec : NULL; 172*2912Sartem #elif sun 173*2912Sartem static struct vfstab v; 174*2912Sartem 175*2912Sartem return getvfsent (handle, &v) == 0 ? v.vfs_special : NULL; 176*2912Sartem #else 177*2912Sartem struct mntent *mnt; 178*2912Sartem 179*2912Sartem mnt = getmntent (handle); 180*2912Sartem 181*2912Sartem if (mount_point != NULL && mnt != NULL) { 182*2912Sartem *mount_point = mnt->mnt_dir; 183*2912Sartem } 184*2912Sartem 185*2912Sartem return mnt ? mnt->mnt_fsname : NULL; 186*2912Sartem #endif 187*2912Sartem } 188*2912Sartem 189*2912Sartem void 190*2912Sartem fstab_close (gpointer handle) 191*2912Sartem { 192*2912Sartem #ifdef __FreeBSD__ 193*2912Sartem endfsent (); 194*2912Sartem #else 195*2912Sartem fclose (handle); 196*2912Sartem #endif 197*2912Sartem } 198*2912Sartem 199*2912Sartem #ifdef __FreeBSD__ 200*2912Sartem #define UMOUNT "/sbin/umount" 201*2912Sartem #elif sun 202*2912Sartem #define UMOUNT "/sbin/umount" 203*2912Sartem #else 204*2912Sartem #define UMOUNT "/bin/umount" 205*2912Sartem #endif 206*2912Sartem 207*2912Sartem void 208*2912Sartem unknown_error (const char *detail) 209*2912Sartem { 210*2912Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.UnknownFailure\n"); 211*2912Sartem fprintf (stderr, "%s\n", detail); 212*2912Sartem exit (1); 213*2912Sartem } 214*2912Sartem 215*2912Sartem 216*2912Sartem static void 217*2912Sartem device_busy (const char *detail) 218*2912Sartem { 219*2912Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.Busy\n"); 220*2912Sartem fprintf (stderr, "%s\n", detail); 221*2912Sartem exit (1); 222*2912Sartem } 223*2912Sartem 224*2912Sartem 225*2912Sartem static void 226*2912Sartem not_mounted (const char *detail) 227*2912Sartem { 228*2912Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.NotMounted\n"); 229*2912Sartem fprintf (stderr, "%s\n", detail); 230*2912Sartem exit (1); 231*2912Sartem } 232*2912Sartem 233*2912Sartem 234*2912Sartem static void 235*2912Sartem not_mounted_by_hal (const char *detail) 236*2912Sartem { 237*2912Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.NotMountedByHal\n"); 238*2912Sartem fprintf (stderr, "%s\n", detail); 239*2912Sartem exit (1); 240*2912Sartem } 241*2912Sartem 242*2912Sartem static void 243*2912Sartem permission_denied_privilege (const char *privilege, const char *uid) 244*2912Sartem { 245*2912Sartem fprintf (stderr, "org.freedesktop.Hal.Device.PermissionDeniedByPolicy\n"); 246*2912Sartem fprintf (stderr, "%s refused uid %s\n", privilege, uid); 247*2912Sartem exit (1); 248*2912Sartem } 249*2912Sartem 250*2912Sartem static void 251*2912Sartem permission_denied_volume_ignore (const char *device) 252*2912Sartem { 253*2912Sartem fprintf (stderr, "org.freedesktop.Hal.Device.Volume.PermissionDenied\n"); 254*2912Sartem fprintf (stderr, "Device has %s volume.ignore set to TRUE. Refusing to mount.\n", device); 255*2912Sartem exit (1); 256*2912Sartem } 257*2912Sartem 258*2912Sartem void 259*2912Sartem handle_unmount (LibHalContext *hal_ctx, 260*2912Sartem #ifdef HAVE_POLKIT 261*2912Sartem LibPolKitContext *pol_ctx, 262*2912Sartem #endif 263*2912Sartem const char *udi, 264*2912Sartem LibHalVolume *volume, LibHalDrive *drive, const char *device, 265*2912Sartem const char *invoked_by_uid, const char *invoked_by_syscon_name, 266*2912Sartem gboolean option_lazy, gboolean option_force, 267*2912Sartem DBusConnection *system_bus) 268*2912Sartem { 269*2912Sartem int i, j; 270*2912Sartem DBusError error; 271*2912Sartem GError *err = NULL; 272*2912Sartem char *sout = NULL; 273*2912Sartem char *serr = NULL; 274*2912Sartem int exit_status; 275*2912Sartem char *args[10]; 276*2912Sartem int na; 277*2912Sartem FILE *hal_mtab_orig; 278*2912Sartem int hal_mtab_orig_len; 279*2912Sartem int num_read; 280*2912Sartem char *hal_mtab_buf; 281*2912Sartem char **lines; 282*2912Sartem char *mount_point_to_unmount; 283*2912Sartem gboolean mounted_by_other_uid; 284*2912Sartem FILE *hal_mtab_new; 285*2912Sartem #ifdef sun 286*2912Sartem adt_export_data_t *adt_data; 287*2912Sartem size_t adt_data_size; 288*2912Sartem #endif 289*2912Sartem 290*2912Sartem #ifdef DEBUG 291*2912Sartem printf ("device = %s\n", device); 292*2912Sartem printf ("invoked by uid = %s\n", invoked_by_uid); 293*2912Sartem printf ("invoked by system bus connection = %s\n", invoked_by_syscon_name); 294*2912Sartem #endif 295*2912Sartem 296*2912Sartem if (volume != NULL) { 297*2912Sartem dbus_error_init (&error); 298*2912Sartem if (libhal_device_get_property_bool (hal_ctx, udi, "volume.ignore", &error) || 299*2912Sartem dbus_error_is_set (&error)) { 300*2912Sartem if (dbus_error_is_set (&error)) { 301*2912Sartem LIBHAL_FREE_DBUS_ERROR (&error); 302*2912Sartem } 303*2912Sartem /* 304*2912Sartem * When device allocation is enabled (bsmconv or TX), we 305*2912Sartem * set volume.ignore on all volumes, but still want 306*2912Sartem * Mount() to succeed when called from the euid=0 307*2912Sartem * device allocation program. 308*2912Sartem */ 309*2912Sartem if (atol (invoked_by_uid) != 0) { 310*2912Sartem permission_denied_volume_ignore (device); 311*2912Sartem } 312*2912Sartem } 313*2912Sartem 314*2912Sartem if (!libhal_volume_is_mounted (volume)) { 315*2912Sartem not_mounted ("According to HAL, the volume is not mounted"); 316*2912Sartem } 317*2912Sartem } 318*2912Sartem 319*2912Sartem 320*2912Sartem /* check hal's mtab file to verify the device to unmount is actually mounted by hal */ 321*2912Sartem hal_mtab_orig = fopen ("/media/.hal-mtab", "r"); 322*2912Sartem if (hal_mtab_orig == NULL) { 323*2912Sartem unknown_error ("Cannot open /media/.hal-mtab"); 324*2912Sartem } 325*2912Sartem if (fseek (hal_mtab_orig, 0L, SEEK_END) != 0) { 326*2912Sartem unknown_error ("Cannot seek to end of /media/.hal-mtab"); 327*2912Sartem } 328*2912Sartem hal_mtab_orig_len = ftell (hal_mtab_orig); 329*2912Sartem if (hal_mtab_orig_len < 0) { 330*2912Sartem unknown_error ("Cannot determine size of /media/.hal-mtab"); 331*2912Sartem } 332*2912Sartem rewind (hal_mtab_orig); 333*2912Sartem hal_mtab_buf = g_new0 (char, hal_mtab_orig_len + 1); 334*2912Sartem num_read = fread (hal_mtab_buf, 1, hal_mtab_orig_len, hal_mtab_orig); 335*2912Sartem if (num_read != hal_mtab_orig_len) { 336*2912Sartem unknown_error ("Cannot read from /media/.hal-mtab"); 337*2912Sartem } 338*2912Sartem fclose (hal_mtab_orig); 339*2912Sartem 340*2912Sartem #ifdef DEBUG 341*2912Sartem printf ("hal_mtab = '%s'\n", hal_mtab_buf); 342*2912Sartem #endif 343*2912Sartem 344*2912Sartem lines = g_strsplit (hal_mtab_buf, "\n", 0); 345*2912Sartem g_free (hal_mtab_buf); 346*2912Sartem 347*2912Sartem mount_point_to_unmount = NULL; 348*2912Sartem mounted_by_other_uid = TRUE; 349*2912Sartem 350*2912Sartem /* find the entry we're going to unmount */ 351*2912Sartem for (i = 0; lines[i] != NULL; i++) { 352*2912Sartem char **line_elements; 353*2912Sartem char *special, *dosp; 354*2912Sartem struct stat st; 355*2912Sartem 356*2912Sartem #ifdef DEBUG 357*2912Sartem printf (" line = '%s'\n", lines[i]); 358*2912Sartem #endif 359*2912Sartem 360*2912Sartem if ((lines[i])[0] == '#') 361*2912Sartem continue; 362*2912Sartem 363*2912Sartem line_elements = g_strsplit (lines[i], "\t", 6); 364*2912Sartem if (g_strv_length (line_elements) == 6) { 365*2912Sartem 366*2912Sartem #ifdef DEBUG 367*2912Sartem printf (" devfile = '%s'\n", line_elements[0]); 368*2912Sartem printf (" uid = '%s'\n", line_elements[1]); 369*2912Sartem printf (" session id = '%s'\n", line_elements[2]); 370*2912Sartem printf (" fs = '%s'\n", line_elements[3]); 371*2912Sartem printf (" options = '%s'\n", line_elements[4]); 372*2912Sartem printf (" mount_point = '%s'\n", line_elements[5]); 373*2912Sartem #endif 374*2912Sartem 375*2912Sartem if (strcmp (line_elements[0], device) == 0) { 376*2912Sartem char *line_to_free; 377*2912Sartem 378*2912Sartem if (strcmp (line_elements[1], invoked_by_uid) == 0) { 379*2912Sartem mounted_by_other_uid = FALSE; 380*2912Sartem } 381*2912Sartem #ifdef sun 382*2912Sartem if (stat("/dev/console", &st) == 0 && 383*2912Sartem st.st_uid == atoi (invoked_by_uid)) { 384*2912Sartem /* 385*2912Sartem * Owner is allowed to take over. Before we have real 386*2912Sartem * ownership in HAL, assume it's the console owner. 387*2912Sartem */ 388*2912Sartem mounted_by_other_uid = FALSE; 389*2912Sartem } 390*2912Sartem #endif /* sun */ 391*2912Sartem mount_point_to_unmount = g_strdup (line_elements[5]); 392*2912Sartem 393*2912Sartem line_to_free = lines[i]; 394*2912Sartem 395*2912Sartem for (j = i; lines[j] != NULL; j++) { 396*2912Sartem lines[j] = lines[j+1]; 397*2912Sartem } 398*2912Sartem lines[j] = NULL; 399*2912Sartem 400*2912Sartem g_free (line_to_free); 401*2912Sartem 402*2912Sartem g_strfreev (line_elements); 403*2912Sartem goto line_found; 404*2912Sartem 405*2912Sartem } 406*2912Sartem 407*2912Sartem } 408*2912Sartem 409*2912Sartem g_strfreev (line_elements); 410*2912Sartem } 411*2912Sartem line_found: 412*2912Sartem 413*2912Sartem if (mount_point_to_unmount == NULL) { 414*2912Sartem not_mounted_by_hal ("Device to unmount is not in /media/.hal-mtab so it is not mounted by HAL"); 415*2912Sartem } 416*2912Sartem 417*2912Sartem /* bail out, unless if we got the "hal-storage-can-unmount-volumes-mounted-by-others" privilege only 418*2912Sartem * if mounted_by_other_uid==TRUE 419*2912Sartem * 420*2912Sartem * We allow uid 0 to actually ensure that Unmount(options=["lazy"], "/dev/blah") works from addon-storage. 421*2912Sartem */ 422*2912Sartem if ((strcmp (invoked_by_uid, "0") != 0) && mounted_by_other_uid) { 423*2912Sartem /* TODO: actually check for privilege "hal-storage-can-unmount-volumes-mounted-by-others" */ 424*2912Sartem permission_denied_privilege ("hal-storage-can-unmount-volumes-mounted-by-others", invoked_by_uid); 425*2912Sartem } 426*2912Sartem 427*2912Sartem /* create new .hal-mtab~ file without the entry we're going to unmount */ 428*2912Sartem hal_mtab_new = fopen ("/media/.hal-mtab~", "w"); 429*2912Sartem if (hal_mtab_new == NULL) { 430*2912Sartem unknown_error ("Cannot create /media/.hal-mtab~"); 431*2912Sartem } 432*2912Sartem for (i = 0; lines[i] != NULL; i++) { 433*2912Sartem if (i > 0) { 434*2912Sartem char anewl[2] = "\n\0"; 435*2912Sartem if (fwrite (anewl, 1, 1, hal_mtab_new) != 1) { 436*2912Sartem unknown_error ("Cannot write to /media/.hal-mtab~"); 437*2912Sartem } 438*2912Sartem } 439*2912Sartem 440*2912Sartem if (fwrite (lines[i], 1, strlen (lines[i]), hal_mtab_new) != strlen (lines[i])) { 441*2912Sartem unknown_error ("Cannot write to /media/.hal-mtab~"); 442*2912Sartem } 443*2912Sartem 444*2912Sartem } 445*2912Sartem fclose (hal_mtab_new); 446*2912Sartem 447*2912Sartem g_strfreev (lines); 448*2912Sartem 449*2912Sartem /* construct arguments to /bin/umount */ 450*2912Sartem na = 0; 451*2912Sartem args[na++] = UMOUNT; 452*2912Sartem if (option_lazy) 453*2912Sartem args[na++] = "-l"; 454*2912Sartem if (option_force) 455*2912Sartem args[na++] = "-f"; 456*2912Sartem args[na++] = (char *) device; 457*2912Sartem args[na++] = NULL; 458*2912Sartem 459*2912Sartem #ifdef DEBUG 460*2912Sartem printf ("will umount %s (mounted at '%s'), mounted_by_other_uid=%d\n", 461*2912Sartem device, mount_point_to_unmount, mounted_by_other_uid); 462*2912Sartem #endif 463*2912Sartem 464*2912Sartem /* invoke /bin/umount */ 465*2912Sartem if (!g_spawn_sync ("/", 466*2912Sartem args, 467*2912Sartem NULL, 468*2912Sartem 0, 469*2912Sartem NULL, 470*2912Sartem NULL, 471*2912Sartem &sout, 472*2912Sartem &serr, 473*2912Sartem &exit_status, 474*2912Sartem &err)) { 475*2912Sartem printf ("Cannot execute %s\n", UMOUNT); 476*2912Sartem unlink ("/media/.hal-mtab~"); 477*2912Sartem unknown_error ("Cannot spawn " UMOUNT); 478*2912Sartem } 479*2912Sartem 480*2912Sartem /* check if unmount was succesful */ 481*2912Sartem if (exit_status != 0) { 482*2912Sartem printf ("%s error %d, stdout='%s', stderr='%s'\n", UMOUNT, exit_status, sout, serr); 483*2912Sartem 484*2912Sartem if (strstr (serr, "device is busy") != NULL) { 485*2912Sartem unlink ("/media/.hal-mtab~"); 486*2912Sartem device_busy (serr); 487*2912Sartem } else { 488*2912Sartem unlink ("/media/.hal-mtab~"); 489*2912Sartem unknown_error (serr); 490*2912Sartem } 491*2912Sartem } 492*2912Sartem 493*2912Sartem #ifdef sun 494*2912Sartem if ((adt_data = get_audit_export_data (system_bus, 495*2912Sartem invoked_by_syscon_name, &adt_data_size)) != NULL) { 496*2912Sartem audit_volume (adt_data, ADT_detach, WEXITSTATUS(exit_status), 497*2912Sartem "solaris.device.mount.removable", 498*2912Sartem mount_point_to_unmount, device, NULL); 499*2912Sartem free (adt_data); 500*2912Sartem } 501*2912Sartem #endif 502*2912Sartem 503*2912Sartem /* unmount was succesful, remove directory we created in Mount() */ 504*2912Sartem #ifdef sun 505*2912Sartem if (strncmp (mount_point_to_unmount, "/media/", 7) == 0) 506*2912Sartem #endif 507*2912Sartem if (g_rmdir (mount_point_to_unmount) != 0) { 508*2912Sartem unlink ("/media/.hal-mtab~"); 509*2912Sartem unknown_error ("Cannot remove directory"); 510*2912Sartem } 511*2912Sartem 512*2912Sartem /* set new .hal-mtab file */ 513*2912Sartem if (rename ("/media/.hal-mtab~", "/media/.hal-mtab") != 0) { 514*2912Sartem unlink ("/media/.hal-mtab~"); 515*2912Sartem unknown_error ("Cannot rename /media/.hal-mtab~ to /media/.hal-mtab"); 516*2912Sartem } 517*2912Sartem 518*2912Sartem #ifdef DEBUG 519*2912Sartem printf ("done unmounting\n"); 520*2912Sartem #endif 521*2912Sartem openlog ("hald", 0, LOG_DAEMON); 522*2912Sartem syslog (LOG_INFO, "unmounted %s from '%s' on behalf of uid %s", device, mount_point_to_unmount, invoked_by_uid); 523*2912Sartem closelog (); 524*2912Sartem 525*2912Sartem g_free (sout); 526*2912Sartem g_free (serr); 527*2912Sartem g_free (mount_point_to_unmount); 528*2912Sartem } 529*2912Sartem 530*2912Sartem #define EJECT "/usr/bin/eject" 531*2912Sartem 532*2912Sartem void 533*2912Sartem handle_eject (LibHalContext *hal_ctx, 534*2912Sartem #ifdef HAVE_POLKIT 535*2912Sartem LibPolKitContext *pol_ctx, 536*2912Sartem #endif 537*2912Sartem const char *udi, 538*2912Sartem LibHalDrive *drive, const char *device, 539*2912Sartem const char *invoked_by_uid, const char *invoked_by_syscon_name, 540*2912Sartem gboolean closetray, DBusConnection *system_bus) 541*2912Sartem { 542*2912Sartem GError *err = NULL; 543*2912Sartem char *sout = NULL; 544*2912Sartem char *serr = NULL; 545*2912Sartem int exit_status; 546*2912Sartem char *args[10]; 547*2912Sartem int na; 548*2912Sartem #ifdef sun 549*2912Sartem adt_export_data_t *adt_data; 550*2912Sartem size_t adt_data_size; 551*2912Sartem #endif 552*2912Sartem /* TODO: should we require privileges here? */ 553*2912Sartem 554*2912Sartem #ifdef DEBUG 555*2912Sartem printf ("device = %s\n", device); 556*2912Sartem printf ("invoked by uid = %s\n", invoked_by_uid); 557*2912Sartem printf ("invoked by system bus connection = %s\n", invoked_by_syscon_name); 558*2912Sartem #endif 559*2912Sartem 560*2912Sartem /* construct arguments to EJECT (e.g. /usr/bin/eject) */ 561*2912Sartem na = 0; 562*2912Sartem args[na++] = EJECT; 563*2912Sartem if (closetray) { 564*2912Sartem args[na++] = "-t"; 565*2912Sartem } 566*2912Sartem args[na++] = (char *) device; 567*2912Sartem args[na++] = NULL; 568*2912Sartem 569*2912Sartem #ifdef sun 570*2912Sartem putenv("EJECT_DIRECT=1"); 571*2912Sartem #endif 572*2912Sartem 573*2912Sartem #ifdef DEBUG 574*2912Sartem printf ("will eject %s\n", device); 575*2912Sartem #endif 576*2912Sartem 577*2912Sartem /* invoke eject command */ 578*2912Sartem if (!g_spawn_sync ("/", 579*2912Sartem args, 580*2912Sartem NULL, 581*2912Sartem 0, 582*2912Sartem NULL, 583*2912Sartem NULL, 584*2912Sartem &sout, 585*2912Sartem &serr, 586*2912Sartem &exit_status, 587*2912Sartem &err)) { 588*2912Sartem printf ("Cannot execute %s\n", EJECT); 589*2912Sartem unknown_error ("Cannot spawn " EJECT); 590*2912Sartem } 591*2912Sartem 592*2912Sartem #ifdef sun 593*2912Sartem /* 594*2912Sartem * Solaris eject returns 4 for manually ejectable media like floppy. 595*2912Sartem * Consider it success. 596*2912Sartem */ 597*2912Sartem if (WEXITSTATUS(exit_status) == 4) { 598*2912Sartem exit_status = 0; 599*2912Sartem } 600*2912Sartem 601*2912Sartem if ((adt_data = get_audit_export_data (system_bus, 602*2912Sartem invoked_by_syscon_name, &adt_data_size)) != NULL) { 603*2912Sartem audit_volume (adt_data, ADT_remove, WEXITSTATUS(exit_status), 604*2912Sartem "solaris.device.mount.removable", NULL, device, NULL); 605*2912Sartem free (adt_data); 606*2912Sartem } 607*2912Sartem #endif /* sun */ 608*2912Sartem 609*2912Sartem /* check if eject was succesful */ 610*2912Sartem if (exit_status != 0) { 611*2912Sartem printf ("%s error %d, stdout='%s', stderr='%s'\n", EJECT, exit_status, sout, serr); 612*2912Sartem 613*2912Sartem unknown_error (serr); 614*2912Sartem } 615*2912Sartem 616*2912Sartem /* eject was succesful... */ 617*2912Sartem 618*2912Sartem #ifdef DEBUG 619*2912Sartem printf ("done ejecting\n"); 620*2912Sartem #endif 621*2912Sartem 622*2912Sartem g_free (sout); 623*2912Sartem g_free (serr); 624*2912Sartem } 625*2912Sartem 626*2912Sartem 627*2912Sartem static int lock_mtab_fd = -1; 628*2912Sartem 629*2912Sartem gboolean 630*2912Sartem lock_hal_mtab (void) 631*2912Sartem { 632*2912Sartem if (lock_mtab_fd >= 0) 633*2912Sartem return TRUE; 634*2912Sartem 635*2912Sartem printf ("%d: XYA attempting to get lock on /media/.hal-mtab-lock\n", getpid ()); 636*2912Sartem 637*2912Sartem lock_mtab_fd = open ("/media/.hal-mtab-lock", O_CREAT | O_RDWR); 638*2912Sartem 639*2912Sartem if (lock_mtab_fd < 0) 640*2912Sartem return FALSE; 641*2912Sartem 642*2912Sartem tryagain: 643*2912Sartem #if sun 644*2912Sartem if (lockf (lock_mtab_fd, F_LOCK, 0) != 0) { 645*2912Sartem #else 646*2912Sartem if (flock (lock_mtab_fd, LOCK_EX) != 0) { 647*2912Sartem #endif 648*2912Sartem if (errno == EINTR) 649*2912Sartem goto tryagain; 650*2912Sartem return FALSE; 651*2912Sartem } 652*2912Sartem 653*2912Sartem printf ("%d: XYA got lock on /media/.hal-mtab-lock\n", getpid ()); 654*2912Sartem 655*2912Sartem 656*2912Sartem return TRUE; 657*2912Sartem } 658*2912Sartem 659*2912Sartem void 660*2912Sartem unlock_hal_mtab (void) 661*2912Sartem { 662*2912Sartem #if sun 663*2912Sartem lockf (lock_mtab_fd, F_ULOCK, 0); 664*2912Sartem #else 665*2912Sartem flock (lock_mtab_fd, LOCK_UN); 666*2912Sartem #endif 667*2912Sartem close (lock_mtab_fd); 668*2912Sartem lock_mtab_fd = -1; 669*2912Sartem printf ("%d: XYA released lock on /media/.hal-mtab-lock\n", getpid ()); 670*2912Sartem } 671*2912Sartem 672*2912Sartem #if sun 673*2912Sartem 674*2912Sartem /* map PolicyKit privilege to RBAC authorization */ 675*2912Sartem char * 676*2912Sartem auth_from_privilege(const char *privilege) 677*2912Sartem { 678*2912Sartem char *authname; 679*2912Sartem int i; 680*2912Sartem 681*2912Sartem if (strcmp (privilege, "hal-storage-removable-mount") == 0) { 682*2912Sartem authname = g_strdup ("solaris.device.mount.removable"); 683*2912Sartem } else if (strcmp (privilege, "hal-storage-removable-mount-all-options") == 0) { 684*2912Sartem authname = g_strdup ("solaris.device.mount.alloptions.removable"); 685*2912Sartem } else if (strcmp (privilege, "hal-storage-fixed-mount") == 0) { 686*2912Sartem authname = g_strdup ("solaris.device.mount.fixed"); 687*2912Sartem } else if (strcmp (privilege, "hal-storage-fixed-mount-all-options") == 0) { 688*2912Sartem authname = g_strdup ("solaris.device.mount.alloptions.fixed"); 689*2912Sartem } else { 690*2912Sartem /* replace '-' with '.' */ 691*2912Sartem authname = g_strdup (privilege); 692*2912Sartem for (i = 0; i < strlen (authname); i++) { 693*2912Sartem if (authname[i] == '-') { 694*2912Sartem authname[i] = '.'; 695*2912Sartem } 696*2912Sartem } 697*2912Sartem } 698*2912Sartem return (authname); 699*2912Sartem } 700*2912Sartem 701*2912Sartem adt_export_data_t * 702*2912Sartem get_audit_export_data(DBusConnection *bus, const char *invoked_by_syscon_name, size_t *data_size) 703*2912Sartem { 704*2912Sartem DBusMessage *message; 705*2912Sartem DBusMessage *reply; 706*2912Sartem DBusMessageIter iter, subiter; 707*2912Sartem DBusError error; 708*2912Sartem int count, bufsize; 709*2912Sartem uchar_t *buf; 710*2912Sartem uchar_t value; 711*2912Sartem 712*2912Sartem message = dbus_message_new_method_call ("org.freedesktop.DBus", 713*2912Sartem "/org/freedesktop/DBus", 714*2912Sartem "org.freedesktop.DBus", 715*2912Sartem "GetAuditSessionData"); 716*2912Sartem if (message == NULL) { 717*2912Sartem printf ("cannot get message\n"); 718*2912Sartem return NULL; 719*2912Sartem } 720*2912Sartem 721*2912Sartem if (!dbus_message_append_args(message, DBUS_TYPE_STRING, &invoked_by_syscon_name, 722*2912Sartem DBUS_TYPE_INVALID)) { 723*2912Sartem dbus_message_unref(message); 724*2912Sartem return NULL; 725*2912Sartem } 726*2912Sartem 727*2912Sartem dbus_error_init (&error); 728*2912Sartem reply = dbus_connection_send_with_reply_and_block (bus, 729*2912Sartem message, -1, 730*2912Sartem &error); 731*2912Sartem if (dbus_error_is_set (&error)) { 732*2912Sartem printf ("send failed %s\n", error.message); 733*2912Sartem dbus_error_free (&error); 734*2912Sartem dbus_message_unref (message); 735*2912Sartem return NULL; 736*2912Sartem } 737*2912Sartem if (reply == NULL) { 738*2912Sartem dbus_message_unref (message); 739*2912Sartem return NULL; 740*2912Sartem } 741*2912Sartem 742*2912Sartem dbus_message_iter_init (reply, &iter); 743*2912Sartem 744*2912Sartem if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY || 745*2912Sartem dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_BYTE) { 746*2912Sartem printf ("expecting an array of byte entries\n"); 747*2912Sartem dbus_message_unref (message); 748*2912Sartem dbus_message_unref (reply); 749*2912Sartem return NULL; 750*2912Sartem } 751*2912Sartem dbus_message_iter_recurse (&iter, &subiter); 752*2912Sartem 753*2912Sartem count = 0; 754*2912Sartem bufsize = 256; 755*2912Sartem buf = (uchar_t *)malloc (bufsize); 756*2912Sartem 757*2912Sartem while (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_BYTE) { 758*2912Sartem if (count == bufsize) { 759*2912Sartem bufsize += 256; 760*2912Sartem buf = realloc (buf, bufsize); 761*2912Sartem if (buf == NULL) { 762*2912Sartem dbus_message_unref (message); 763*2912Sartem dbus_message_unref (reply); 764*2912Sartem return NULL; 765*2912Sartem } 766*2912Sartem } 767*2912Sartem 768*2912Sartem dbus_message_iter_get_basic (&subiter, &value); 769*2912Sartem buf[count++] = value; 770*2912Sartem dbus_message_iter_next(&subiter); 771*2912Sartem } 772*2912Sartem 773*2912Sartem dbus_message_unref (message); 774*2912Sartem dbus_message_unref (reply); 775*2912Sartem 776*2912Sartem *data_size = count; 777*2912Sartem if (count == 0) { 778*2912Sartem free (buf); 779*2912Sartem buf = NULL; 780*2912Sartem } 781*2912Sartem 782*2912Sartem return (adt_export_data_t *)buf; 783*2912Sartem } 784*2912Sartem 785*2912Sartem void 786*2912Sartem audit_volume(const adt_export_data_t *imported_state, au_event_t event_id, 787*2912Sartem int result, const char *auth_used, const char *mount_point, 788*2912Sartem const char *device, const char *options) 789*2912Sartem { 790*2912Sartem adt_session_data_t *ah; 791*2912Sartem adt_event_data_t *event; 792*2912Sartem 793*2912Sartem if (adt_start_session(&ah, imported_state, 0) != 0) { 794*2912Sartem printf ("adt_start_session failed %d\n", errno); 795*2912Sartem return; 796*2912Sartem } 797*2912Sartem if ((event = adt_alloc_event(ah, event_id)) == NULL) { 798*2912Sartem printf ("adt_alloc_event(ADT_attach)\n", errno); 799*2912Sartem return; 800*2912Sartem } 801*2912Sartem 802*2912Sartem switch (event_id) { 803*2912Sartem case ADT_attach: 804*2912Sartem event->adt_attach.auth_used = (char *)auth_used; 805*2912Sartem event->adt_attach.mount_point = (char *)mount_point; 806*2912Sartem event->adt_attach.device = (char *)device; 807*2912Sartem event->adt_attach.options = (char *)options; 808*2912Sartem break; 809*2912Sartem case ADT_detach: 810*2912Sartem event->adt_detach.auth_used = (char *)auth_used; 811*2912Sartem event->adt_detach.mount_point = (char *)mount_point; 812*2912Sartem event->adt_detach.device = (char *)device; 813*2912Sartem event->adt_detach.options = (char *)options; 814*2912Sartem break; 815*2912Sartem case ADT_remove: 816*2912Sartem event->adt_remove.auth_used = (char *)auth_used; 817*2912Sartem event->adt_remove.mount_point = (char *)mount_point; 818*2912Sartem event->adt_remove.device = (char *)device; 819*2912Sartem break; 820*2912Sartem default: 821*2912Sartem goto out; 822*2912Sartem } 823*2912Sartem 824*2912Sartem if (result == 0) { 825*2912Sartem if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 826*2912Sartem printf ("adt_put_event(%d, success)\n", event_id); 827*2912Sartem } 828*2912Sartem } else { 829*2912Sartem if (adt_put_event(event, ADT_FAILURE, result) != 0) { 830*2912Sartem printf ("adt_put_event(%d, failure)\n", event_id); 831*2912Sartem } 832*2912Sartem } 833*2912Sartem out: 834*2912Sartem adt_free_event(event); 835*2912Sartem (void) adt_end_session(ah); 836*2912Sartem } 837*2912Sartem 838*2912Sartem #endif /* sun */ 839