]> gitweb.michael.orlitzky.com - apply-default-acl.git/commitdiff
Add documentation for the safe_open() and safe_open_ex() functions.
authorMichael Orlitzky <michael@orlitzky.com>
Mon, 26 Feb 2018 13:38:14 +0000 (08:38 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Mon, 26 Feb 2018 19:10:29 +0000 (14:10 -0500)
src/apply-default-acl.c

index 188c1f2e9b30a365cde1c2f80b16df6b1bba51b3..3cf3060a115e2be50f75822d13319e5362684a82 100644 (file)
 #define SNPRINTF_ERROR -1
 #define STAT_ERROR -1
 
+
+/**
+ * @brief The recursive portion of the @c safe_open function, used to
+ *   open a file descriptor in a symlink-safe way when combined with
+ *   the @c O_NOFOLLOW flag.
+ *
+ * @param at_fd
+ *   A file descriptor relative to which @c pathname will be opened.
+ *
+ * @param pathname
+ *   The path to the file/directory/whatever whose descriptor you want.
+ *
+ * @return a file descriptor for @c pathname if everything goes well,
+ *   and @c OPEN_ERROR if not.
+ */
 int safe_open_ex(int at_fd, char* pathname, int flags) {
   if (pathname != NULL && strlen(pathname) == 0) {
     /* Oops, went one level to deep with nothing to do. */
@@ -79,6 +94,29 @@ int safe_open_ex(int at_fd, char* pathname, int flags) {
 }
 
 
+/**
+ * @brief A version of @c open that is completely symlink-safe when
+ *   used with the @c O_NOFOLLOW flag.
+ *
+ * The @c openat function exists to ensure that you can anchor one
+ * path to a particular directory while opening it; however, if you
+ * open "b/c/d" relative to "/a", then even the @c openat function will
+ * still follow symlinks in the "b" component. This can be exploited
+ * by an attacker to make you open the wrong path.
+ *
+ * To avoid that problem, this function uses a recursive
+ * implementation that opens every path from the root, one level at a
+ * time. So "a" is opened relative to "/", and then "b" is opened
+ * relative to "/a", and then "c" is opened relative to "/a/b",
+ * etc. When the @c O_NOFOLLOW flag is used, this approach ensures
+ * that no symlinks in any component are followed.
+ *
+ * @param pathname
+ *   The path to the file/directory/whatever whose descriptor you want.
+ *
+ * @return a file descriptor for @c pathname if everything goes well,
+ *   and @c OPEN_ERROR if not.
+ */
 int safe_open(const char* pathname, int flags) {
   if (pathname == NULL || strlen(pathname) == 0 || pathname[0] == '\0') {
     /* error? */