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; 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; char* final;
Ref<Descriptor> dir = OpenDirContainingPath(ctx, Ref<Descriptor>(this), Ref<Descriptor> dir = OpenDirContainingPath(ctx, Ref<Descriptor>(this),
filename, &final); filename, &final);
if ( !dir ) if ( !dir )
return -1; return -1;
int ret = dir->vnode->unlink(ctx, final); int ret = -1;
delete[] final; if ( ret < 0 && (flags & AT_REMOVEFILE) )
return ret; ret = dir->vnode->unlink(ctx, final);
} if ( ret < 0 && (flags & AT_REMOVEDIR) )
ret = dir->vnode->rmdir(ctx, final);
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);
delete[] final; delete[] final;
return ret; return ret;
} }

View File

@ -80,8 +80,7 @@ public:
mode_t mode = 0); mode_t mode = 0);
int mkdir(ioctx_t* ctx, const char* filename, mode_t mode); int mkdir(ioctx_t* ctx, const char* filename, mode_t mode);
int link(ioctx_t* ctx, const char* filename, Ref<Descriptor> node); int link(ioctx_t* ctx, const char* filename, Ref<Descriptor> node);
int unlink(ioctx_t* ctx, const char* filename); int unlinkat(ioctx_t* ctx, const char* filename, int flags);
int rmdir(ioctx_t* ctx, const char* filename);
int symlink(ioctx_t* ctx, const char* oldname, const char* filename); int symlink(ioctx_t* ctx, const char* oldname, const char* filename);
ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz); ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz);
int tcgetwincurpos(ioctx_t* ctx, struct wincurpos* wcp); 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] == '.' ) if ( ((const char*) dirent.d_name)[0] == '.' )
continue; 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->lseek(&ctx.ioctx, 0, SEEK_SET);
} }
ctx.links.Reset(); 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. // Unmap the pages and return the physical frames for reallocation.
for ( size_t i = 0; i < initrd_addr_alloc.size; i += Page::Size() ) 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) int sys_unlinkat(int dirfd, const char* path, int flags)
{ {
if ( !(flags & (AT_REMOVEFILE | AT_REMOVEDIR)) )
flags |= AT_REMOVEFILE;
char* pathcopy = GetStringFromUser(path); char* pathcopy = GetStringFromUser(path);
if ( !pathcopy ) if ( !pathcopy )
return -1; return -1;
@ -213,11 +211,7 @@ int sys_unlinkat(int dirfd, const char* path, int flags)
const char* relpath = pathcopy; const char* relpath = pathcopy;
Ref<Descriptor> from = PrepareLookup(&relpath, dirfd); Ref<Descriptor> from = PrepareLookup(&relpath, dirfd);
if ( !from ) { delete[] pathcopy; return -1; } if ( !from ) { delete[] pathcopy; return -1; }
int ret = -1; int ret = from->unlinkat(&ctx, relpath, flags);
if ( ret < 0 && (flags & AT_REMOVEFILE) )
ret = from->unlink(&ctx, relpath);
if ( ret < 0 && (flags & AT_REMOVEDIR) )
ret = from->rmdir(&ctx, relpath);
delete[] pathcopy; delete[] pathcopy;
return ret; return ret;
} }