"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "subprojects/bubblewrap/bind-mount.c" between
flatpak-1.15.1.tar.xz and flatpak-1.15.2.tar.xz

About: Flatpak is a Linux application sandboxing and distribution framework. Pre-release.

bind-mount.c  (flatpak-1.15.1.tar.xz):bind-mount.c  (flatpak-1.15.2.tar.xz)
skipping to change at line 381 skipping to change at line 381
end_tab = collect_mounts (&mount_tab[0], &lines[root]); end_tab = collect_mounts (&mount_tab[0], &lines[root]);
assert (end_tab == &mount_tab[n_mounts]); assert (end_tab == &mount_tab[n_mounts]);
return steal_pointer (&mount_tab); return steal_pointer (&mount_tab);
} }
bind_mount_result bind_mount_result
bind_mount (int proc_fd, bind_mount (int proc_fd,
const char *src, const char *src,
const char *dest, const char *dest,
bind_option_t options) bind_option_t options,
char **failing_path)
{ {
bool readonly = (options & BIND_READONLY) != 0; bool readonly = (options & BIND_READONLY) != 0;
bool devices = (options & BIND_DEVICES) != 0; bool devices = (options & BIND_DEVICES) != 0;
bool recursive = (options & BIND_RECURSIVE) != 0; bool recursive = (options & BIND_RECURSIVE) != 0;
unsigned long current_flags, new_flags; unsigned long current_flags, new_flags;
cleanup_mount_tab MountTab mount_tab = NULL; cleanup_mount_tab MountTab mount_tab = NULL;
cleanup_free char *resolved_dest = NULL; cleanup_free char *resolved_dest = NULL;
cleanup_free char *dest_proc = NULL; cleanup_free char *dest_proc = NULL;
cleanup_free char *oldroot_dest_proc = NULL; cleanup_free char *oldroot_dest_proc = NULL;
cleanup_free char *kernel_case_combination = NULL; cleanup_free char *kernel_case_combination = NULL;
skipping to change at line 409 skipping to change at line 410
} }
/* The mount operation will resolve any symlinks in the destination /* The mount operation will resolve any symlinks in the destination
path, so to find it in the mount table we need to do that too. */ path, so to find it in the mount table we need to do that too. */
resolved_dest = realpath (dest, NULL); resolved_dest = realpath (dest, NULL);
if (resolved_dest == NULL) if (resolved_dest == NULL)
return BIND_MOUNT_ERROR_REALPATH_DEST; return BIND_MOUNT_ERROR_REALPATH_DEST;
dest_fd = open (resolved_dest, O_PATH | O_CLOEXEC); dest_fd = open (resolved_dest, O_PATH | O_CLOEXEC);
if (dest_fd < 0) if (dest_fd < 0)
return BIND_MOUNT_ERROR_REOPEN_DEST; {
if (failing_path != NULL)
*failing_path = steal_pointer (&resolved_dest);
return BIND_MOUNT_ERROR_REOPEN_DEST;
}
/* If we are in a case-insensitive filesystem, mountinfo might contain a /* If we are in a case-insensitive filesystem, mountinfo might contain a
* different case combination of the path we requested to mount. * different case combination of the path we requested to mount.
* This is due to the fact that the kernel, as of the beginning of 2021, * This is due to the fact that the kernel, as of the beginning of 2021,
* populates mountinfo with whatever case combination first appeared in the * populates mountinfo with whatever case combination first appeared in the
* dcache; kernel developers plan to change this in future so that it * dcache; kernel developers plan to change this in future so that it
* reflects the on-disk encoding instead. * reflects the on-disk encoding instead.
* To avoid throwing an error when this happens, we use readlink() result * To avoid throwing an error when this happens, we use readlink() result
* instead of the provided @root_mount, so that we can compare the mountinfo * instead of the provided @root_mount, so that we can compare the mountinfo
* entries with the same case combination that the kernel is expected to * entries with the same case combination that the kernel is expected to
* use. */ * use. */
dest_proc = xasprintf ("/proc/self/fd/%d", dest_fd); dest_proc = xasprintf ("/proc/self/fd/%d", dest_fd);
oldroot_dest_proc = get_oldroot_path (dest_proc); oldroot_dest_proc = get_oldroot_path (dest_proc);
kernel_case_combination = readlink_malloc (oldroot_dest_proc); kernel_case_combination = readlink_malloc (oldroot_dest_proc);
if (kernel_case_combination == NULL) if (kernel_case_combination == NULL)
return BIND_MOUNT_ERROR_READLINK_DEST_PROC_FD; {
if (failing_path != NULL)
*failing_path = steal_pointer (&resolved_dest);
return BIND_MOUNT_ERROR_READLINK_DEST_PROC_FD;
}
mount_tab = parse_mountinfo (proc_fd, kernel_case_combination); mount_tab = parse_mountinfo (proc_fd, kernel_case_combination);
if (mount_tab[0].mountpoint == NULL) if (mount_tab[0].mountpoint == NULL)
{ {
if (failing_path != NULL)
*failing_path = steal_pointer (&kernel_case_combination);
errno = EINVAL; errno = EINVAL;
return BIND_MOUNT_ERROR_FIND_DEST_MOUNT; return BIND_MOUNT_ERROR_FIND_DEST_MOUNT;
} }
assert (path_equal (mount_tab[0].mountpoint, kernel_case_combination)); assert (path_equal (mount_tab[0].mountpoint, kernel_case_combination));
current_flags = mount_tab[0].options; current_flags = mount_tab[0].options;
new_flags = current_flags | (devices ? 0 : MS_NODEV) | MS_NOSUID | (readonly ? MS_RDONLY : 0); new_flags = current_flags | (devices ? 0 : MS_NODEV) | MS_NOSUID | (readonly ? MS_RDONLY : 0);
if (new_flags != current_flags && if (new_flags != current_flags &&
mount ("none", resolved_dest, mount ("none", resolved_dest,
NULL, MS_SILENT | MS_BIND | MS_REMOUNT | new_flags, NULL) != 0) NULL, MS_SILENT | MS_BIND | MS_REMOUNT | new_flags, NULL) != 0)
return BIND_MOUNT_ERROR_REMOUNT_DEST; {
if (failing_path != NULL)
*failing_path = steal_pointer (&resolved_dest);
return BIND_MOUNT_ERROR_REMOUNT_DEST;
}
/* We need to work around the fact that a bind mount does not apply the flags, so we need to manually /* We need to work around the fact that a bind mount does not apply the flags, so we need to manually
* apply the flags to all submounts in the recursive case. * apply the flags to all submounts in the recursive case.
* Note: This does not apply the flags to mounts which are later propagated in to this namespace. * Note: This does not apply the flags to mounts which are later propagated in to this namespace.
*/ */
if (recursive) if (recursive)
{ {
for (i = 1; mount_tab[i].mountpoint != NULL; i++) for (i = 1; mount_tab[i].mountpoint != NULL; i++)
{ {
current_flags = mount_tab[i].options; current_flags = mount_tab[i].options;
new_flags = current_flags | (devices ? 0 : MS_NODEV) | MS_NOSUID | (re adonly ? MS_RDONLY : 0); new_flags = current_flags | (devices ? 0 : MS_NODEV) | MS_NOSUID | (re adonly ? MS_RDONLY : 0);
if (new_flags != current_flags && if (new_flags != current_flags &&
mount ("none", mount_tab[i].mountpoint, mount ("none", mount_tab[i].mountpoint,
NULL, MS_SILENT | MS_BIND | MS_REMOUNT | new_flags, NULL) ! = 0) NULL, MS_SILENT | MS_BIND | MS_REMOUNT | new_flags, NULL) ! = 0)
{ {
/* If we can't read the mountpoint we can't remount it, but that s hould /* If we can't read the mountpoint we can't remount it, but that s hould
be safe to ignore because its not something the user can access . */ be safe to ignore because its not something the user can access . */
if (errno != EACCES) if (errno != EACCES)
return BIND_MOUNT_ERROR_REMOUNT_SUBMOUNT; {
if (failing_path != NULL)
*failing_path = xstrdup (mount_tab[i].mountpoint);
return BIND_MOUNT_ERROR_REMOUNT_SUBMOUNT;
}
} }
} }
} }
return BIND_MOUNT_SUCCESS; return BIND_MOUNT_SUCCESS;
} }
/** /**
* Return a string representing bind_mount_result, like strerror(). * Return a string representing bind_mount_result, like strerror().
* If want_errno_p is non-NULL, *want_errno_p is used to indicate whether * If want_errno_p is non-NULL, *want_errno_p is used to indicate whether
* it would make sense to print strerror(saved_errno). * it would make sense to print strerror(saved_errno).
*/ */
const char * static char *
bind_mount_result_to_string (bind_mount_result res, bind_mount_result_to_string (bind_mount_result res,
const char *failing_path,
bool *want_errno_p) bool *want_errno_p)
{ {
const char *string; char *string = NULL;
bool want_errno = TRUE; bool want_errno = TRUE;
switch (res) switch (res)
{ {
case BIND_MOUNT_ERROR_MOUNT: case BIND_MOUNT_ERROR_MOUNT:
string = "Unable to mount source on destination"; string = xstrdup ("Unable to mount source on destination");
break; break;
case BIND_MOUNT_ERROR_REALPATH_DEST: case BIND_MOUNT_ERROR_REALPATH_DEST:
string = "realpath(destination)"; string = xstrdup ("realpath(destination)");
break; break;
case BIND_MOUNT_ERROR_REOPEN_DEST: case BIND_MOUNT_ERROR_REOPEN_DEST:
string = "open(destination, O_PATH)"; string = xasprintf ("open(\"%s\", O_PATH)", failing_path);
break; break;
case BIND_MOUNT_ERROR_READLINK_DEST_PROC_FD: case BIND_MOUNT_ERROR_READLINK_DEST_PROC_FD:
string = "readlink(/proc/self/fd/<destination>)"; string = xasprintf ("readlink(/proc/self/fd/N) for \"%s\"", failing_path );
break; break;
case BIND_MOUNT_ERROR_FIND_DEST_MOUNT: case BIND_MOUNT_ERROR_FIND_DEST_MOUNT:
string = "Unable to find destination in mount table"; string = xasprintf ("Unable to find \"%s\" in mount table", failing_path );
want_errno = FALSE; want_errno = FALSE;
break; break;
case BIND_MOUNT_ERROR_REMOUNT_DEST: case BIND_MOUNT_ERROR_REMOUNT_DEST:
string = "Unable to remount destination with correct flags"; string = xasprintf ("Unable to remount destination \"%s\" with correct f
lags",
failing_path);
break; break;
case BIND_MOUNT_ERROR_REMOUNT_SUBMOUNT: case BIND_MOUNT_ERROR_REMOUNT_SUBMOUNT:
string = "Unable to remount recursively with correct flags"; string = xasprintf ("Unable to apply mount flags: remount \"%s\"",
failing_path);
break; break;
case BIND_MOUNT_SUCCESS: case BIND_MOUNT_SUCCESS:
string = "Success"; string = xstrdup ("Success");
break; break;
default: default:
string = "(unknown/invalid bind_mount_result)"; string = xstrdup ("(unknown/invalid bind_mount_result)");
break; break;
} }
if (want_errno_p != NULL) if (want_errno_p != NULL)
*want_errno_p = want_errno; *want_errno_p = want_errno;
return string; return string;
} }
void void
die_with_bind_result (bind_mount_result res, die_with_bind_result (bind_mount_result res,
int saved_errno, int saved_errno,
const char *failing_path,
const char *format, const char *format,
...) ...)
{ {
va_list args; va_list args;
bool want_errno = TRUE; bool want_errno = TRUE;
char *message;
fprintf (stderr, "bwrap: "); fprintf (stderr, "bwrap: ");
va_start (args, format); va_start (args, format);
vfprintf (stderr, format, args); vfprintf (stderr, format, args);
va_end (args); va_end (args);
fprintf (stderr, ": %s", bind_mount_result_to_string (res, &want_errno)); message = bind_mount_result_to_string (res, failing_path, &want_errno);
fprintf (stderr, ": %s", message);
/* message is leaked, but we're exiting unsuccessfully anyway, so ignore */
if (want_errno) if (want_errno)
fprintf (stderr, ": %s", strerror (saved_errno)); fprintf (stderr, ": %s", strerror (saved_errno));
fprintf (stderr, "\n"); fprintf (stderr, "\n");
exit (1); exit (1);
} }
 End of changes. 21 change blocks. 
17 lines changed or deleted 49 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)