#include <sys/socket.h>
#include "macro.h"
+#include "missing_fcntl.h"
#include "stdio-util.h"
/* maximum length of fdname */
#define EBADF_PAIR { -EBADF, -EBADF }
#define EBADF_TRIPLET { -EBADF, -EBADF, -EBADF }
+/* Flags that are safe to have set on an FD given to a privileged service to operate on.
+ * This ensures that clients can't trick a privileged service into giving access to a file the client
+ * doesn't already have access to (especially via something like O_PATH).
+ *
+ * O_NOFOLLOW: For some reason the kernel will return this flag from fcntl; it doesn't go away immediately
+ * after open(). It should have no effect whatsoever to an already-opened FD, but if it does
+ * it's decreasing the risk to a privileged service since it disables symlink following.
+ *
+ * RAW_O_LARGEFILE: glibc secretly sets this and neglects to hide it from us if we call fcntl. See comment
+ * in missing_fcntl.h for more details about this.
+ */
+#define SAFE_FD_FLAGS (O_ACCMODE|O_NOFOLLOW|RAW_O_LARGEFILE)
+#define UNSAFE_FD_FLAGS(flags) ((unsigned)(flags) & ~SAFE_FD_FLAGS)
+
int close_nointr(int fd);
int safe_close(int fd);
void safe_close_pair(int p[static 2]);
#include "fd-util.h"
#include "home-util.h"
#include "homed-bus.h"
-#include "missing_fcntl.h"
#include "stat-util.h"
#include "strv.h"
/* Refuse fds w/ unexpected flags set. In particular, we don't want to permit O_PATH FDs, since
* those don't actually guarantee that the client has access to the file. */
- if ((flags & ~(O_ACCMODE|RAW_O_LARGEFILE)) != 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "FD for %s has unexpected flags set", filename);
+ if (UNSAFE_FD_FLAGS(flags) != 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "FD for %s has unexpected flags set: 0%o",
+ filename, UNSAFE_FD_FLAGS(flags));
r = hashmap_put(blobs, filename, FD_TO_PTR(fd));
if (r < 0)
#include "journald-wall.h"
#include "memfd-util.h"
#include "memory-util.h"
-#include "missing_fcntl.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
return;
}
- if ((flags & ~(O_ACCMODE|RAW_O_LARGEFILE)) != 0) {
- log_ratelimit_error(JOURNAL_LOG_RATELIMIT, "Unexpected flags of passed memory fd, ignoring message: %m");
+ if (UNSAFE_FD_FLAGS(flags) != 0) {
+ log_ratelimit_error(JOURNAL_LOG_RATELIMIT,
+ "Unexpected flags of passed memory fd (0%o), ignoring message: %m",
+ UNSAFE_FD_FLAGS(flags));
return;
}