Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions bind-mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,36 @@ bind_mount (int proc_fd,
return BIND_MOUNT_ERROR_REOPEN_DEST;
}

struct mount_attr attr = {
.attr_clr = 0,
.attr_set = MOUNT_ATTR_NOSUID,
};

if (!devices)
attr.attr_set |= MOUNT_ATTR_NODEV;

if (readonly)
attr.attr_set |= MOUNT_ATTR_RDONLY;

unsigned int setattr_flags = AT_EMPTY_PATH;

if (recursive)
setattr_flags |= AT_RECURSIVE;

if (mount_setattr_wrapper (dest_fd, "", setattr_flags, &attr, sizeof(attr)) == 0)
{
return BIND_MOUNT_SUCCESS;
}
else if (errno != ENOSYS)
{
if (failing_path != NULL)
*failing_path = steal_pointer (&resolved_dest);

return BIND_MOUNT_ERROR_MOUNT_SETATTR;
}

/* mount_setattr(2) isn't available, so we'll have to do this the hard way: */

/* If we are in a case-insensitive filesystem, mountinfo might contain a
* 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,
Expand Down Expand Up @@ -543,6 +573,10 @@ bind_mount_result_to_string (bind_mount_result res,
failing_path);
break;

case BIND_MOUNT_ERROR_MOUNT_SETATTR:
string = xasprintf ("mount_setattr() failed at \"%s\"", failing_path);
break;

case BIND_MOUNT_SUCCESS:
string = xstrdup ("Success");
break;
Expand Down Expand Up @@ -596,6 +630,7 @@ die_with_bind_result (bind_mount_result res,
case BIND_MOUNT_ERROR_REOPEN_DEST:
case BIND_MOUNT_ERROR_READLINK_DEST_PROC_FD:
case BIND_MOUNT_ERROR_FIND_DEST_MOUNT:
case BIND_MOUNT_ERROR_MOUNT_SETATTR:
case BIND_MOUNT_SUCCESS:
default:
fprintf (stderr, ": %s", strerror (saved_errno));
Expand Down
1 change: 1 addition & 0 deletions bind-mount.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ typedef enum
BIND_MOUNT_ERROR_FIND_DEST_MOUNT,
BIND_MOUNT_ERROR_REMOUNT_DEST,
BIND_MOUNT_ERROR_REMOUNT_SUBMOUNT,
BIND_MOUNT_ERROR_MOUNT_SETATTR,
} bind_mount_result;

bind_mount_result bind_mount (int proc_fd,
Expand Down
12 changes: 12 additions & 0 deletions utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1083,3 +1083,15 @@ strappend_escape_for_mount_options (StringBuilder *dest, const char *src)
src++;
}
}

int
mount_setattr_wrapper (int dirfd, const char *path, unsigned int flags,
struct mount_attr *attr, size_t size)
{
#ifdef __NR_mount_setattr
return syscall (__NR_mount_setattr, dirfd, path, flags, attr, size);
#else
errno = ENOSYS;
return -1;
#endif
}
29 changes: 29 additions & 0 deletions utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,32 @@ void strappendf (StringBuilder *dest,
...);
void strappend_escape_for_mount_options (StringBuilder *dest,
const char *src);

#ifndef MOUNT_ATTR_RDONLY
struct mount_attr
{
__u64 attr_set;
__u64 attr_clr;
__u64 propagation;
__u64 userns_fd;
};

#define MOUNT_ATTR_RDONLY 0x00000001
#define MOUNT_ATTR_NOSUID 0x00000002
#define MOUNT_ATTR_NODEV 0x00000004
#define MOUNT_ATTR_NOEXEC 0x00000008
#define MOUNT_ATTR__ATIME 0x00000070
#define MOUNT_ATTR_RELATIME 0x00000000
#define MOUNT_ATTR_NOATIME 0x00000010
#define MOUNT_ATTR_STRICTATIME 0x00000020
#define MOUNT_ATTR_NODIRATIME 0x00000080
#define MOUNT_ATTR_IDMAP 0x00100000
#define MOUNT_ATTR_NOSYMFOLLOW 0x00200000
#endif

#ifndef AT_RECURSIVE
#define AT_RECURSIVE 0x8000
#endif

int mount_setattr_wrapper (int dirfd, const char *path, unsigned int flags,
struct mount_attr *attr, size_t size);