[ovs-dev] [PATCH v4 2/3] chutil: Add hardness amplification versions of chmod/chown

Daniele Di Proietto diproiettod at ovn.org
Tue Oct 4 02:16:15 UTC 2016


2016-08-19 16:48 GMT-07:00 Aaron Conole <aconole at redhat.com>:

> For certain types of files (in particular Unix Domain Sockets), the
> standard
> fchmod/fchown calls have strange side effects.  While Unix Domain Sockets
> have their own particular quirks depending on the system, there may be
> other
> files where Open vSwitch would operate on the file without a concrete file
> handle.  To detect, and possibly prevent, file system races when operating
> on
> these files, two new functions are added (ovs_kchmod and ovs_kchown), which
> perform hardness amplification and column-wise traversal as described in
> https://www.usenix.org/legacy/event/fast08/tech/full_papers/
> tsafrir/tsafrir_html/index.html
>
> Fallbacks are provided which return ENOTSUP on systems where the
> POSIX1.2008
> function calls for {fchmod,fchown,fstat,readlink,open}at are not
> available.
>
> Signed-off-by: Aaron Conole <aconole at redhat.com>
> ---
> v3->v4:
> * Complete rewrite using both directory traversal and hardness
> amplification.
>   The check for the *at were added for the travis build - AIUI FreeBSD does
>   provide those functions, but I did not test there.
>
>  configure.ac        |   2 +-
>  lib/chutil-unix.c   | 304 ++++++++++++++++++++++++++++++
> ++++++++++++++++++++++
>  lib/chutil.h        |   4 +
>  tests/test-chutil.c |  92 ++++++++++++----
>  4 files changed, 382 insertions(+), 20 deletions(-)
>
> +/* Checks whether the relative path element is a symlink.  If an error
> + * occurs, returns -1.  If the path is a symlink, returns 1.  Otherwise,
> + * returns 0.  The stat struct, and target, are output variables and are
> + * considered valid unless the return value is -1.  In the case that the
> + * hardness Amplification fails, errno will be set to EBADFD. */
> +static int is_symlink(int dirfd, const char *path_elem, char target[],
> +                      size_t target_len, struct stat *s)
> +{
> +    struct stat s_cmp;
> +    int result;
> +    for (int k = 0; k < K_ROUNDS; ++k) {
> +        result = fstatat(dirfd, path_elem, s, 0);
> +        if (!k) {
> +            s_cmp = *s;
> +        } else if (!cmp_stat(&s_cmp, s)){
>

It looks like a false positive, but gcc 4.8 complains that 's_cmp' may be
uninitialized here.


> +            return -1;
> +        }
> +    }
> +
> +    if (!result && S_ISLNK(s->st_mode)) {
> +        result = readlinkat(dirfd, path_elem, target, target_len);
> +        if (result != -1) {
> +            target[result] = '\0';
> +            result = 1;
> +        }
> +    }
> +    return result;
> +}
> +
>

[...]



More information about the dev mailing list