In a few places we use the FWRITE() macro to open a file, replace it's
contents with a given string and close it again. There's no real
reason this needs to be a macro rather than just a function though.
Turn it into a function 'write_file()' and make some ancillary
cleanups while we're there:
- Add a return code so the caller can handle giving a useful error message
- Handle the case of short write()s (unlikely, but possible)
- Add O_TRUNC, to make sure we replace the existing contents entirely
Signed-off-by: David Gibson
---
isolation.c | 17 +++++++++--------
pasta.c | 4 ++--
util.c | 33 +++++++++++++++++++++++++++++++++
util.h | 13 +------------
4 files changed, 45 insertions(+), 22 deletions(-)
diff --git a/isolation.c b/isolation.c
index 6ba5830..fda9cad 100644
--- a/isolation.c
+++ b/isolation.c
@@ -129,7 +129,8 @@ void isolate_initial(void)
*/
void isolate_user(uid_t uid, gid_t gid, bool use_userns, const char *userns)
{
- char nsmap[BUFSIZ];
+ char uidmap[BUFSIZ];
+ char gidmap[BUFSIZ];
/* First set our UID & GID in the original namespace */
if (setgroups(0, NULL)) {
@@ -184,14 +185,14 @@ void isolate_user(uid_t uid, gid_t gid, bool use_userns, const char *userns)
}
/* Configure user and group mappings */
- snprintf(nsmap, BUFSIZ, "0 %u 1", uid);
- FWRITE("/proc/self/uid_map", nsmap, "Cannot set uid_map in namespace");
+ snprintf(uidmap, BUFSIZ, "0 %u 1", uid);
+ snprintf(gidmap, BUFSIZ, "0 %u 1", gid);
- FWRITE("/proc/self/setgroups", "deny",
- "Cannot write to setgroups in namespace");
-
- snprintf(nsmap, BUFSIZ, "0 %u 1", gid);
- FWRITE("/proc/self/gid_map", nsmap, "Cannot set gid_map in namespace");
+ if (write_file("/proc/self/uid_map", uidmap) ||
+ write_file("/proc/self/setgroups", "deny") ||
+ write_file("/proc/self/gid_map", gidmap)) {
+ warn("Couldn't configure user namespace");
+ }
}
/**
diff --git a/pasta.c b/pasta.c
index c72efe5..6314a29 100644
--- a/pasta.c
+++ b/pasta.c
@@ -166,8 +166,8 @@ static int pasta_setup_ns(void *arg)
{
const struct pasta_setup_ns_arg *a;
- FWRITE("/proc/sys/net/ipv4/ping_group_range", "0 0",
- "Cannot set ping_group_range, ICMP requests might fail");
+ if (write_file("/proc/sys/net/ipv4/ping_group_range", "0 0"))
+ warn("Cannot set ping_group_range, ICMP requests might fail");
a = (const struct pasta_setup_ns_arg *)arg;
execvp(a->exe, a->argv);
diff --git a/util.c b/util.c
index 6b86ead..884b1f4 100644
--- a/util.c
+++ b/util.c
@@ -547,3 +547,36 @@ int fls(unsigned long x)
return y;
}
+
+/**
+ * write_file() - Replace contents of file with a string
+ * @path: File to write
+ * @buf: String to write
+ *
+ * Return: 0 on success, -1 on any error
+ */
+int write_file(const char *path, const char *buf)
+{
+ int fd = open(path, O_WRONLY | O_TRUNC | O_CLOEXEC);
+ size_t len = strlen(buf);
+
+ if (fd < 0) {
+ warn("Could not open %s: %s", path, strerror(errno));
+ return -1;
+ }
+
+ while (len) {
+ ssize_t rc = write(fd, buf, len);
+
+ if (rc <= 0) {
+ warn("Couldn't write to %s: %s", path, strerror(errno));
+ break;
+ }
+
+ buf += rc;
+ len -= rc;
+ }
+
+ close(fd);
+ return len == 0 ? 0 : -1;
+}
diff --git a/util.h b/util.h
index 0c06e34..f957522 100644
--- a/util.h
+++ b/util.h
@@ -58,18 +58,6 @@ void trace_init(int enable);
#define TMPDIR "/tmp"
#endif
-#define FWRITE(path, buf, str) \
- do { \
- int flags = O_WRONLY | O_CLOEXEC; \
- int fd = open(path, flags); \
- \
- if (fd < 0 || \
- write(fd, buf, strlen(buf)) != (int)strlen(buf)) \
- warn(str); \
- if (fd >= 0) \
- close(fd); \
- } while (0)
-
#define V4 0
#define V6 1
#define IP_VERSIONS 2
@@ -215,5 +203,6 @@ int ns_enter(const struct ctx *c);
void write_pidfile(int fd, pid_t pid);
int __daemon(int pidfile_fd, int devnull_fd);
int fls(unsigned long x);
+int write_file(const char *path, const char *buf);
#endif /* UTIL_H */
--
2.37.3