lkml.org 
[lkml]   [2021]   [Feb]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 6/8] unix_bind_bsd(): move done_path_create() call after dealing with ->bindlock
    Final preparations for doing unlink on failure past the successful
    mknod. We can't hold ->bindlock over ->mknod() or ->unlink(), since
    either might do sb_start_write() (e.g. on overlayfs). However, we
    can do it while holding filesystem and VFS locks - doing
    kern_path_create()
    vfs_mknod()
    grab ->bindlock
    if u->addr had been set
    drop ->bindlock
    done_path_create
    return -EINVAL
    else
    assign the address to socket
    drop ->bindlock
    done_path_create
    return 0
    would be deadlock-free. Here we massage unix_bind_bsd() to that
    form. We are still doing equivalent transformations.

    Next commit will *not* be an equivalent transformation - it will
    add a call of vfs_unlink() before done_path_create() in "alread bound"
    case.

    Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
    ---
    net/unix/af_unix.c | 24 ++++++++++--------------
    1 file changed, 10 insertions(+), 14 deletions(-)

    diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
    index 36b88c8c438b..d55035a9695f 100644
    --- a/net/unix/af_unix.c
    +++ b/net/unix/af_unix.c
    @@ -989,7 +989,7 @@ static int unix_bind_bsd(struct sock *sk, struct unix_address *addr)
    struct unix_sock *u = unix_sk(sk);
    umode_t mode = S_IFSOCK |
    (SOCK_INODE(sk->sk_socket)->i_mode & ~current_umask());
    - struct path parent, path;
    + struct path parent;
    struct dentry *dentry;
    unsigned int hash;
    int err;
    @@ -1006,38 +1006,34 @@ static int unix_bind_bsd(struct sock *sk, struct unix_address *addr)
    * All right, let's create it.
    */
    err = security_path_mknod(&parent, dentry, mode, 0);
    - if (!err) {
    + if (!err)
    err = vfs_mknod(d_inode(parent.dentry), dentry, mode, 0);
    - if (!err) {
    - path.mnt = mntget(parent.mnt);
    - path.dentry = dget(dentry);
    - }
    - }
    - done_path_create(&parent, dentry);
    +
    if (err) {
    if (err == -EEXIST)
    err = -EADDRINUSE;
    + done_path_create(&parent, dentry);
    return err;
    }
    -
    err = mutex_lock_interruptible(&u->bindlock);
    if (err) {
    - path_put(&path);
    + done_path_create(&parent, dentry);
    return err;
    }
    -
    if (u->addr) {
    mutex_unlock(&u->bindlock);
    - path_put(&path);
    + done_path_create(&parent, dentry);
    return -EINVAL;
    }

    addr->hash = UNIX_HASH_SIZE;
    - hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1);
    + hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1);
    spin_lock(&unix_table_lock);
    - u->path = path;
    + u->path.mnt = mntget(parent.mnt);
    + u->path.dentry = dget(dentry);
    __unix_set_addr(sk, addr, hash);
    mutex_unlock(&u->bindlock);
    + done_path_create(&parent, dentry);
    return 0;
    }

    --
    2.11.0
    \
     
     \ /
      Last update: 2021-02-19 05:24    [W:3.202 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site