diff mbox series

[07/13] 9p: darwin: Properly translate AT_REMOVEDIR flag

Message ID cd4661a5e122b1dcd848ff5cdf202e728a0359a8.1527310210.git.keno@alumni.harvard.edu
State New
Headers show
Series 9p: Add support for Darwin | expand

Commit Message

Keno Fischer May 26, 2018, 5:23 a.m. UTC
From: Keno Fischer <keno@alumni.harvard.edu>

This code relied on P9_DOTL_AT_REMOVEDIR and AT_REMOVEDIR having the same
numerical value, but on Darwin, they do not.

Signed-off-by: Keno Fischer <keno@juliacomputing.com>
---
 hw/9pfs/9p-local.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

Comments

Greg Kurz May 29, 2018, 8:43 p.m. UTC | #1
On Sat, 26 May 2018 01:23:09 -0400
keno@juliacomputing.com wrote:

> From: Keno Fischer <keno@alumni.harvard.edu>
> 
> This code relied on P9_DOTL_AT_REMOVEDIR and AT_REMOVEDIR having the same
> numerical value, but on Darwin, they do not.
> 
> Signed-off-by: Keno Fischer <keno@juliacomputing.com>
> ---
>  hw/9pfs/9p-local.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
> index 6e0b2e8..c55ea25 100644
> --- a/hw/9pfs/9p-local.c
> +++ b/hw/9pfs/9p-local.c
> @@ -1376,7 +1376,17 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
>          return -1;
>      }
>  
> -    ret = local_unlinkat_common(ctx, dirfd, name, flags);
> +    if ((flags & ~P9_DOTL_AT_REMOVEDIR) != 0) {

The != 0 isn't needed but...

> +        errno = EINVAL;
> +        return -1;

... I'm more concerned about this new error path. How can this happen ?

> +    }
> +
> +    size_t rflags = 0;

Please declare this at the beginning of the function.

> +    if (flags & P9_DOTL_AT_REMOVEDIR) {
> +        rflags |= AT_REMOVEDIR;
> +    }
> +
> +    ret = local_unlinkat_common(ctx, dirfd, name, rflags);
>      close_preserve_errno(dirfd);
>      return ret;
>  }
Keno Fischer May 31, 2018, 4:25 p.m. UTC | #2
>> +        errno = EINVAL;
>> +        return -1;
>
> ... I'm more concerned about this new error path. How can this happen ?
>

As far as I can tell, the flags come from the client without any
intermediate error
checking. Since the Darwin constants do not match the Linux constants (which
have the same numerical values as the 9p constants), we need to perform this
checking/translation somewhere to ensure correct behavior.
Is there a more appropriate place to put this check?
Greg Kurz May 31, 2018, 7:44 p.m. UTC | #3
On Thu, 31 May 2018 12:25:49 -0400
Keno Fischer <keno@juliacomputing.com> wrote:

> >> +        errno = EINVAL;
> >> +        return -1;  
> >
> > ... I'm more concerned about this new error path. How can this happen ?
> >  
> 
> As far as I can tell, the flags come from the client without any
> intermediate error
> checking. 

Indeed :-\

> Since the Darwin constants do not match the Linux constants (which
> have the same numerical values as the 9p constants), we need to perform this
> checking/translation somewhere to ensure correct behavior.
> Is there a more appropriate place to put this check?

The right thing to do would be to check and translate the flag from
P9_DOTL_AT_REMOVEDIR to AT_REMOVEDIR in the core 9p server code.
diff mbox series

Patch

diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 6e0b2e8..c55ea25 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -1376,7 +1376,17 @@  static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
         return -1;
     }
 
-    ret = local_unlinkat_common(ctx, dirfd, name, flags);
+    if ((flags & ~P9_DOTL_AT_REMOVEDIR) != 0) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    size_t rflags = 0;
+    if (flags & P9_DOTL_AT_REMOVEDIR) {
+        rflags |= AT_REMOVEDIR;
+    }
+
+    ret = local_unlinkat_common(ctx, dirfd, name, rflags);
     close_preserve_errno(dirfd);
     return ret;
 }