Fix unlinkat potentially following paths twice.
This commit is contained in:
parent
8c0252300e
commit
5589085084
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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() )
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue