diff options
Diffstat (limited to 'gdb')
| -rw-r--r-- | gdb/linux-nat.c | 14 | ||||
| -rw-r--r-- | gdb/linux-nat.h | 3 | ||||
| -rw-r--r-- | gdb/nat/linux-namespaces.c | 69 | ||||
| -rw-r--r-- | gdb/nat/linux-namespaces.h | 5 |
4 files changed, 91 insertions, 0 deletions
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 2f98060..8f5f978 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -4585,6 +4585,20 @@ linux_nat_target::fileio_open (struct inferior *inf, const char *filename, return fd; } +/* Implementation of to_fileio_lstat. */ + +int +linux_nat_target::fileio_lstat (struct inferior *inf, const char *filename, + struct stat *sb, fileio_error *target_errno) +{ + int r = linux_mntns_lstat (linux_nat_fileio_pid_of (inf), filename, sb); + + if (r == -1) + *target_errno = host_to_fileio_error (errno); + + return r; +} + /* Implementation of to_fileio_readlink. */ std::optional<std::string> diff --git a/gdb/linux-nat.h b/gdb/linux-nat.h index 6e53991..21ec309 100644 --- a/gdb/linux-nat.h +++ b/gdb/linux-nat.h @@ -108,6 +108,9 @@ public: const char *filename, fileio_error *target_errno) override; + int fileio_lstat (struct inferior *inf, const char *filename, + struct stat *sb, fileio_error *target_errno) override; + int fileio_unlink (struct inferior *inf, const char *filename, fileio_error *target_errno) override; diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c index a3a38d8..8fe3206 100644 --- a/gdb/nat/linux-namespaces.c +++ b/gdb/nat/linux-namespaces.c @@ -233,6 +233,12 @@ enum mnsh_msg_type MNSH_RET_INT. */ MNSH_REQ_SETNS, + /* A request that the helper call lstat. The single + argument (the filename) should be passed in BUF, and + should include a terminating NUL character. The helper + should respond with a MNSH_RET_INTSTR. */ + MNSH_REQ_LSTAT, + /* A request that the helper call open. Arguments should be passed in BUF, INT1 and INT2. The filename (in BUF) should include a terminating NUL character. The helper @@ -284,6 +290,10 @@ mnsh_debug_print_message (enum mnsh_msg_type type, res += "ERROR"; break; + case MNSH_REQ_LSTAT: + res += "LSTAT"; + break; + case MNSH_REQ_SETNS: res += "SETNS"; break; @@ -511,6 +521,20 @@ mnsh_handle_setns (int sock, int fd, int nstype) return mnsh_return_int (sock, result, errno); } + +/* Handle a MNSH_REQ_LSTAT message. Must be async-signal-safe. */ + +static ssize_t +mnsh_handle_lstat (int sock, const char *filename) +{ + struct stat sb; + int stat_ok = lstat (filename, &sb); + + return mnsh_return_intstr (sock, stat_ok, &sb, + stat_ok == -1 ? 0 : sizeof (sb), + errno); +} + /* Handle a MNSH_REQ_OPEN message. Must be async-signal-safe. */ static ssize_t @@ -571,6 +595,11 @@ mnsh_main (int sock) response = mnsh_handle_setns (sock, fd, int1); break; + case MNSH_REQ_LSTAT: + if (size > 0 && buf[size - 1] == '\0') + response = mnsh_handle_lstat (sock, buf); + break; + case MNSH_REQ_OPEN: if (size > 0 && buf[size - 1] == '\0') response = mnsh_handle_open (sock, buf, int1, int2); @@ -761,6 +790,10 @@ mnsh_maybe_mourn_peer (void) mnsh_send_message (helper->sock, MNSH_REQ_OPEN, -1, flags, mode, \ filename, strlen (filename) + 1) +#define mnsh_send_lstat(helper, filename) \ + mnsh_send_message (helper->sock, MNSH_REQ_LSTAT, -1, 0, 0, \ + filename, strlen (filename) + 1) + #define mnsh_send_unlink(helper, filename) \ mnsh_send_message (helper->sock, MNSH_REQ_UNLINK, -1, 0, 0, \ filename, strlen (filename) + 1) @@ -944,6 +977,42 @@ linux_mntns_access_fs (pid_t pid) /* See nat/linux-namespaces.h. */ int +linux_mntns_lstat (pid_t pid, const char *filename, + struct stat *sb) +{ + enum mnsh_fs_code access = linux_mntns_access_fs (pid); + + if (access == MNSH_FS_ERROR) + return -1; + + if (access == MNSH_FS_DIRECT) + return lstat (filename, sb); + + gdb_assert (access == MNSH_FS_HELPER); + + struct linux_mnsh *helper = linux_mntns_get_helper (); + + ssize_t size = mnsh_send_lstat (helper, filename); + if (size < 0) + return -1; + + int stat_ok, error; + size = mnsh_recv_intstr (helper, &stat_ok, &error, sb, sizeof (*sb)); + + if (size < 0) + { + stat_ok = -1; + errno = error; + } + else + gdb_assert (stat_ok == -1 || size == sizeof (*sb)); + + return stat_ok; +} + +/* See nat/linux-namespaces.h. */ + +int linux_mntns_open_cloexec (pid_t pid, const char *filename, int flags, mode_t mode) { diff --git a/gdb/nat/linux-namespaces.h b/gdb/nat/linux-namespaces.h index cfaccde..a9a99f1 100644 --- a/gdb/nat/linux-namespaces.h +++ b/gdb/nat/linux-namespaces.h @@ -64,6 +64,11 @@ enum linux_ns_type extern int linux_ns_same (pid_t pid, enum linux_ns_type type); +/* Like lstat(2), but in the mount namespace of process PID. */ + +extern int linux_mntns_lstat (pid_t pid, const char *filename, + struct stat *sb); + /* Like gdb_open_cloexec, but in the mount namespace of process PID. */ |
