[PATCH 3/3 v2] selftests: add devpts selftests

2018-03-11 Thread Christian Brauner
This adds a simple test to check whether /proc//fd/ symlinks are
correctly pointing to /dev/pts/ devices when attached to a terminal.

Signed-off-by: Christian Brauner 
---
ChangeLog v1->v2:
* patch added
ChangeLog v0->v1:
* patch not present
---
 tools/testing/selftests/Makefile |   1 +
 tools/testing/selftests/filesystems/.gitignore   |   1 +
 tools/testing/selftests/filesystems/Makefile |   3 +-
 tools/testing/selftests/filesystems/devpts_pts.c | 191 +++
 4 files changed, 195 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/filesystems/devpts_pts.c

diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 7442dfb73b7f..dbda89c9d9b9 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -7,6 +7,7 @@ TARGETS += cpufreq
 TARGETS += cpu-hotplug
 TARGETS += efivarfs
 TARGETS += exec
+TARGETS += filesystems
 TARGETS += firmware
 TARGETS += ftrace
 TARGETS += futex
diff --git a/tools/testing/selftests/filesystems/.gitignore 
b/tools/testing/selftests/filesystems/.gitignore
index 31d6e426b6d4..8449cf6716ce 100644
--- a/tools/testing/selftests/filesystems/.gitignore
+++ b/tools/testing/selftests/filesystems/.gitignore
@@ -1 +1,2 @@
 dnotify_test
+devpts_pts
diff --git a/tools/testing/selftests/filesystems/Makefile 
b/tools/testing/selftests/filesystems/Makefile
index 13a73bf725b5..b9b5d2f68990 100644
--- a/tools/testing/selftests/filesystems/Makefile
+++ b/tools/testing/selftests/filesystems/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
-TEST_PROGS := dnotify_test
+TEST_PROGS := dnotify_test \
+   devpts_pts
 all: $(TEST_PROGS)
 
 include ../lib.mk
diff --git a/tools/testing/selftests/filesystems/devpts_pts.c 
b/tools/testing/selftests/filesystems/devpts_pts.c
new file mode 100644
index ..10a73e422600
--- /dev/null
+++ b/tools/testing/selftests/filesystems/devpts_pts.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static bool terminal_dup2(int duplicate, int original)
+{
+   int ret;
+
+   ret = dup2(duplicate, original);
+   if (ret < 0)
+   return false;
+
+   return true;
+}
+
+static int lxc_terminal_set_stdfds(int fd)
+{
+   int i;
+
+   if (fd < 0)
+   return 0;
+
+   for (i = 0; i < 3; i++)
+   if (!terminal_dup2(fd, (int[]){STDIN_FILENO, STDOUT_FILENO,
+  STDERR_FILENO}[i]))
+   return -1;
+
+   return 0;
+}
+
+static int login_pty(int fd)
+{
+   int ret;
+
+   setsid();
+
+   ret = ioctl(fd, TIOCSCTTY, NULL);
+   if (ret < 0)
+   return -1;
+
+   ret = lxc_terminal_set_stdfds(fd);
+   if (ret < 0)
+   return -1;
+
+   if (fd > STDERR_FILENO)
+   close(fd);
+
+   return 0;
+}
+
+static int wait_for_pid(pid_t pid)
+{
+   int status, ret;
+
+again:
+   ret = waitpid(pid, , 0);
+   if (ret == -1) {
+   if (errno == EINTR)
+   goto again;
+   return -1;
+   }
+   if (ret != pid)
+   goto again;
+
+   if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+   return -1;
+
+   return 0;
+}
+
+int main(int argc, char *argv[])
+{
+   int master = -1, ret = -1, slave = -1;
+   int fret = EXIT_FAILURE;
+
+   if (!isatty(STDIN_FILENO)) {
+   fprintf(stderr, "Standard input file desciptor is not attached "
+   "to a terminal. Skipping test\n");
+   goto do_cleanup;
+   }
+
+   ret = unshare(CLONE_NEWNS);
+   if (ret < 0) {
+   fprintf(stderr, "Failed to unshare mount namespace\n");
+   goto do_cleanup;
+   }
+
+   ret = mount("", "/", NULL, MS_PRIVATE | MS_REC, 0);
+   if (ret < 0) {
+   fprintf(stderr, "Failed to make \"/\" MS_PRIVATE in new mount "
+   "namespace\n");
+   goto do_cleanup;
+   }
+
+   ret = mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL);
+   if (ret < 0) {
+   fprintf(stderr, "Failed to bind mount \"/dev/pts/ptmx\" to "
+   "\"/dev/ptmx\" mount namespace\n");
+   goto do_cleanup;
+   }
+
+   master = open("/dev/ptmx", O_RDWR | O_NOCTTY | O_CLOEXEC);
+   if (master < 0) {
+   fprintf(stderr, "Failed to open \"/dev/ptmx\"\n");
+   goto do_cleanup;
+   }
+
+   ret = grantpt(master);
+   if (ret < 0) {
+   fprintf(stderr, "Failed to grant access to terminal\n");
+   goto do_cleanup;
+   }
+
+   ret = unlockpt(master);
+   if (ret < 0) {
+   

[PATCH 3/3 v2] selftests: add devpts selftests

2018-03-11 Thread Christian Brauner
This adds a simple test to check whether /proc//fd/ symlinks are
correctly pointing to /dev/pts/ devices when attached to a terminal.

Signed-off-by: Christian Brauner 
---
ChangeLog v1->v2:
* patch added
ChangeLog v0->v1:
* patch not present
---
 tools/testing/selftests/Makefile |   1 +
 tools/testing/selftests/filesystems/.gitignore   |   1 +
 tools/testing/selftests/filesystems/Makefile |   3 +-
 tools/testing/selftests/filesystems/devpts_pts.c | 191 +++
 4 files changed, 195 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/filesystems/devpts_pts.c

diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 7442dfb73b7f..dbda89c9d9b9 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -7,6 +7,7 @@ TARGETS += cpufreq
 TARGETS += cpu-hotplug
 TARGETS += efivarfs
 TARGETS += exec
+TARGETS += filesystems
 TARGETS += firmware
 TARGETS += ftrace
 TARGETS += futex
diff --git a/tools/testing/selftests/filesystems/.gitignore 
b/tools/testing/selftests/filesystems/.gitignore
index 31d6e426b6d4..8449cf6716ce 100644
--- a/tools/testing/selftests/filesystems/.gitignore
+++ b/tools/testing/selftests/filesystems/.gitignore
@@ -1 +1,2 @@
 dnotify_test
+devpts_pts
diff --git a/tools/testing/selftests/filesystems/Makefile 
b/tools/testing/selftests/filesystems/Makefile
index 13a73bf725b5..b9b5d2f68990 100644
--- a/tools/testing/selftests/filesystems/Makefile
+++ b/tools/testing/selftests/filesystems/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
-TEST_PROGS := dnotify_test
+TEST_PROGS := dnotify_test \
+   devpts_pts
 all: $(TEST_PROGS)
 
 include ../lib.mk
diff --git a/tools/testing/selftests/filesystems/devpts_pts.c 
b/tools/testing/selftests/filesystems/devpts_pts.c
new file mode 100644
index ..10a73e422600
--- /dev/null
+++ b/tools/testing/selftests/filesystems/devpts_pts.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static bool terminal_dup2(int duplicate, int original)
+{
+   int ret;
+
+   ret = dup2(duplicate, original);
+   if (ret < 0)
+   return false;
+
+   return true;
+}
+
+static int lxc_terminal_set_stdfds(int fd)
+{
+   int i;
+
+   if (fd < 0)
+   return 0;
+
+   for (i = 0; i < 3; i++)
+   if (!terminal_dup2(fd, (int[]){STDIN_FILENO, STDOUT_FILENO,
+  STDERR_FILENO}[i]))
+   return -1;
+
+   return 0;
+}
+
+static int login_pty(int fd)
+{
+   int ret;
+
+   setsid();
+
+   ret = ioctl(fd, TIOCSCTTY, NULL);
+   if (ret < 0)
+   return -1;
+
+   ret = lxc_terminal_set_stdfds(fd);
+   if (ret < 0)
+   return -1;
+
+   if (fd > STDERR_FILENO)
+   close(fd);
+
+   return 0;
+}
+
+static int wait_for_pid(pid_t pid)
+{
+   int status, ret;
+
+again:
+   ret = waitpid(pid, , 0);
+   if (ret == -1) {
+   if (errno == EINTR)
+   goto again;
+   return -1;
+   }
+   if (ret != pid)
+   goto again;
+
+   if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+   return -1;
+
+   return 0;
+}
+
+int main(int argc, char *argv[])
+{
+   int master = -1, ret = -1, slave = -1;
+   int fret = EXIT_FAILURE;
+
+   if (!isatty(STDIN_FILENO)) {
+   fprintf(stderr, "Standard input file desciptor is not attached "
+   "to a terminal. Skipping test\n");
+   goto do_cleanup;
+   }
+
+   ret = unshare(CLONE_NEWNS);
+   if (ret < 0) {
+   fprintf(stderr, "Failed to unshare mount namespace\n");
+   goto do_cleanup;
+   }
+
+   ret = mount("", "/", NULL, MS_PRIVATE | MS_REC, 0);
+   if (ret < 0) {
+   fprintf(stderr, "Failed to make \"/\" MS_PRIVATE in new mount "
+   "namespace\n");
+   goto do_cleanup;
+   }
+
+   ret = mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL);
+   if (ret < 0) {
+   fprintf(stderr, "Failed to bind mount \"/dev/pts/ptmx\" to "
+   "\"/dev/ptmx\" mount namespace\n");
+   goto do_cleanup;
+   }
+
+   master = open("/dev/ptmx", O_RDWR | O_NOCTTY | O_CLOEXEC);
+   if (master < 0) {
+   fprintf(stderr, "Failed to open \"/dev/ptmx\"\n");
+   goto do_cleanup;
+   }
+
+   ret = grantpt(master);
+   if (ret < 0) {
+   fprintf(stderr, "Failed to grant access to terminal\n");
+   goto do_cleanup;
+   }
+
+   ret = unlockpt(master);
+   if (ret < 0) {
+   fprintf(stderr, "Failed to unlock