Fix unlinkat potentially following paths twice.

This commit is contained in:
Jonas 'Sortie' Termansen 2015-05-13 18:49:31 +02:00
parent 8c0252300e
commit 5589085084
4 changed files with 14 additions and 25 deletions

View File

@ -606,26 +606,22 @@ int Descriptor::link(ioctx_t* ctx, const char* filename, Ref<Descriptor> node)
return ret;
}
int Descriptor::unlink(ioctx_t* ctx, const char* filename)
int Descriptor::unlinkat(ioctx_t* ctx, const char* filename, int flags)
{
if ( flags & ~(AT_REMOVEFILE | AT_REMOVEDIR) )
return errno = EINVAL, -1;
if ( !(flags & (AT_REMOVEFILE | AT_REMOVEDIR)) )
flags |= AT_REMOVEFILE;
char* final;
Ref<Descriptor> dir = OpenDirContainingPath(ctx, Ref<Descriptor>(this),
filename, &final);
if ( !dir )
return -1;
int ret = dir->vnode->unlink(ctx, final);
delete[] final;
return ret;
}
int Descriptor::rmdir(ioctx_t* ctx, const char* filename)
{
char* final;
Ref<Descriptor> dir = OpenDirContainingPath(ctx, Ref<Descriptor>(this),
filename, &final);
if ( !dir )
return -1;
int ret = dir->vnode->rmdir(ctx, final);
int ret = -1;
if ( ret < 0 && (flags & AT_REMOVEFILE) )
ret = dir->vnode->unlink(ctx, final);
if ( ret < 0 && (flags & AT_REMOVEDIR) )
ret = dir->vnode->rmdir(ctx, final);
delete[] final;
return ret;
}

View File

@ -80,8 +80,7 @@ public:
mode_t mode = 0);
int mkdir(ioctx_t* ctx, const char* filename, mode_t mode);
int link(ioctx_t* ctx, const char* filename, Ref<Descriptor> node);
int unlink(ioctx_t* ctx, const char* filename);
int rmdir(ioctx_t* ctx, const char* filename);
int unlinkat(ioctx_t* ctx, const char* filename, int flags);
int symlink(ioctx_t* ctx, const char* oldname, const char* filename);
ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz);
int tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp);

View File

@ -392,13 +392,13 @@ bool ExtractFromPhysicalInto(addr_t physaddr, size_t size, Ref<Descriptor> desc)
{
if ( ((const char*) dirent.d_name)[0] == '.' )
continue;
ctx.links->unlink(&ctx.ioctx, dirent.d_name);
ctx.links->unlinkat(&ctx.ioctx, dirent.d_name, AT_REMOVEFILE);
ctx.links->lseek(&ctx.ioctx, 0, SEEK_SET);
}
ctx.links.Reset();
desc->rmdir(&ctx.ioctx, ".initrd-links");
desc->unlinkat(&ctx.ioctx, ".initrd-links", AT_REMOVEDIR);
// Unmap the pages and return the physical frames for reallocation.
for ( size_t i = 0; i < initrd_addr_alloc.size; i += Page::Size() )

View File

@ -204,8 +204,6 @@ int sys_faccessat(int dirfd, const char* path, int /*mode*/, int flags)
int sys_unlinkat(int dirfd, const char* path, int flags)
{
if ( !(flags & (AT_REMOVEFILE | AT_REMOVEDIR)) )
flags |= AT_REMOVEFILE;
char* pathcopy = GetStringFromUser(path);
if ( !pathcopy )
return -1;
@ -213,11 +211,7 @@ int sys_unlinkat(int dirfd, const char* path, int flags)
const char* relpath = pathcopy;
Ref<Descriptor> from = PrepareLookup(&relpath, dirfd);
if ( !from ) { delete[] pathcopy; return -1; }
int ret = -1;
if ( ret < 0 && (flags & AT_REMOVEFILE) )
ret = from->unlink(&ctx, relpath);
if ( ret < 0 && (flags & AT_REMOVEDIR) )
ret = from->rmdir(&ctx, relpath);
int ret = from->unlinkat(&ctx, relpath, flags);
delete[] pathcopy;
return ret;
}