libc: resolve symlinks in execve
This patch complements the commit "libc: execve" with the ability to execute files stored at arbitrary sub directories of the file system. Issue #3481 Issue #3500
This commit is contained in:
parent
697d496093
commit
ab5187d673
|
@ -16,9 +16,13 @@ install_config {
|
||||||
<arg value="name_of_executeable"/>
|
<arg value="name_of_executeable"/>
|
||||||
<arg value="100"/>
|
<arg value="100"/>
|
||||||
<libc stdin="/null" stdout="/log" stderr="/log"/>
|
<libc stdin="/null" stdout="/log" stderr="/log"/>
|
||||||
<vfs> <null/> <log/> </vfs>
|
<vfs> <rom name="test-execve"/> <null/> <log/> </vfs>
|
||||||
</config>
|
</config>
|
||||||
<route> <any-service> <parent/> </any-service> </route>
|
<route>
|
||||||
|
<service name="ROM" label="/test-execve">
|
||||||
|
<parent label="test-execve"/> </service>
|
||||||
|
<any-service> <parent/> </any-service>
|
||||||
|
</route>
|
||||||
</start>
|
</start>
|
||||||
</config>
|
</config>
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <internal/call_func.h>
|
#include <internal/call_func.h>
|
||||||
#include <internal/init.h>
|
#include <internal/init.h>
|
||||||
#include <internal/errno.h>
|
#include <internal/errno.h>
|
||||||
|
#include <internal/file_operations.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
@ -161,6 +162,13 @@ extern "C" int execve(char const *filename,
|
||||||
return Libc::Errno(EACCES);
|
return Libc::Errno(EACCES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Libc::Absolute_path resolved_path;
|
||||||
|
try {
|
||||||
|
Libc::resolve_symlinks(filename, resolved_path); }
|
||||||
|
catch (Libc::Symlink_resolve_error) {
|
||||||
|
warning("execve: ", filename, " does not exist");
|
||||||
|
return Libc::Errno(ENOENT); }
|
||||||
|
|
||||||
/* capture environment variables and args to libc-internal heap */
|
/* capture environment variables and args to libc-internal heap */
|
||||||
Libc::String_array *saved_env_vars =
|
Libc::String_array *saved_env_vars =
|
||||||
new (*_alloc_ptr) Libc::String_array(*_alloc_ptr, envp);
|
new (*_alloc_ptr) Libc::String_array(*_alloc_ptr, envp);
|
||||||
|
@ -169,7 +177,7 @@ extern "C" int execve(char const *filename,
|
||||||
new (*_alloc_ptr) Libc::String_array(*_alloc_ptr, argv);
|
new (*_alloc_ptr) Libc::String_array(*_alloc_ptr, argv);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_main_ptr = Dynamic_linker::respawn<main_fn_ptr>(*_env_ptr, filename, "main");
|
_main_ptr = Dynamic_linker::respawn<main_fn_ptr>(*_env_ptr, resolved_path.string(), "main");
|
||||||
}
|
}
|
||||||
catch (Dynamic_linker::Invalid_symbol) {
|
catch (Dynamic_linker::Invalid_symbol) {
|
||||||
error("Dynamic_linker::respawn could not obtain binary entry point");
|
error("Dynamic_linker::respawn could not obtain binary entry point");
|
||||||
|
|
|
@ -478,12 +478,21 @@ struct Libc::Forked_child : Child_policy, Child_ready
|
||||||
Route resolve_session_request(Service::Name const &name,
|
Route resolve_session_request(Service::Name const &name,
|
||||||
Session_label const &label) override
|
Session_label const &label) override
|
||||||
{
|
{
|
||||||
|
Session_label rewritten_label = label;
|
||||||
|
|
||||||
Service *service_ptr = nullptr;
|
Service *service_ptr = nullptr;
|
||||||
if (_state == State::STARTING_UP && name == Clone_session::service_name())
|
if (_state == State::STARTING_UP && name == Clone_session::service_name())
|
||||||
service_ptr = &_local_clone_service.service;
|
service_ptr = &_local_clone_service.service;
|
||||||
|
|
||||||
if (name == Rom_session::service_name()) {
|
if (name == Rom_session::service_name()) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Strip off the originating child name to allow the application of
|
||||||
|
* routing rules based on the leading path elements, regardless
|
||||||
|
* of which child in the process hierarchy requests a ROM.
|
||||||
|
*/
|
||||||
|
rewritten_label = label.last_element();
|
||||||
|
|
||||||
try { service_ptr = &_local_rom_services.matching_service(name, label); }
|
try { service_ptr = &_local_rom_services.matching_service(name, label); }
|
||||||
catch (...) { }
|
catch (...) { }
|
||||||
|
|
||||||
|
@ -496,7 +505,7 @@ struct Libc::Forked_child : Child_policy, Child_ready
|
||||||
|
|
||||||
if (service_ptr)
|
if (service_ptr)
|
||||||
return Route { .service = *service_ptr,
|
return Route { .service = *service_ptr,
|
||||||
.label = label,
|
.label = rewritten_label,
|
||||||
.diag = Session::Diag() };
|
.diag = Session::Diag() };
|
||||||
|
|
||||||
throw Service_denied();
|
throw Service_denied();
|
||||||
|
|
35
repos/libports/src/lib/libc/internal/file_operations.h
Normal file
35
repos/libports/src/lib/libc/internal/file_operations.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* \brief Libc-internal file operations
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2019-09-23
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBC__INTERNAL__FILE_OPERATIONS_H_
|
||||||
|
#define _LIBC__INTERNAL__FILE_OPERATIONS_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <os/path.h>
|
||||||
|
|
||||||
|
/* libc includes */
|
||||||
|
#include <limits.h> /* for 'PATH_MAX' */
|
||||||
|
|
||||||
|
/* libc-internal includes */
|
||||||
|
#include <internal/types.h>
|
||||||
|
|
||||||
|
namespace Libc {
|
||||||
|
|
||||||
|
typedef Genode::Path<PATH_MAX> Absolute_path;
|
||||||
|
|
||||||
|
class Symlink_resolve_error : Exception { };
|
||||||
|
|
||||||
|
void resolve_symlinks(char const *path, Absolute_path &resolved_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _LIBC__INTERNAL__FILE_OPERATIONS_H_ */
|
|
@ -87,7 +87,7 @@ install_config {
|
||||||
</dir>
|
</dir>
|
||||||
</vfs>
|
</vfs>
|
||||||
|
|
||||||
<policy label_prefix="vfs_rom" root="/bin"/>
|
<policy label_prefix="vfs_rom" root="/"/>
|
||||||
<default-policy root="/" writeable="yes"/>
|
<default-policy root="/" writeable="yes"/>
|
||||||
</config>
|
</config>
|
||||||
</start>
|
</start>
|
||||||
|
@ -103,7 +103,7 @@ install_config {
|
||||||
</route>
|
</route>
|
||||||
</start>
|
</start>
|
||||||
|
|
||||||
<start name="bash" caps="1000">
|
<start name="/bin/bash" caps="1000">
|
||||||
<resource name="RAM" quantum="30M" />
|
<resource name="RAM" quantum="30M" />
|
||||||
<config>
|
<config>
|
||||||
<libc stdin="/dev/terminal" stdout="/dev/terminal"
|
<libc stdin="/dev/terminal" stdout="/dev/terminal"
|
||||||
|
@ -115,9 +115,9 @@ install_config {
|
||||||
</config>
|
</config>
|
||||||
<route>
|
<route>
|
||||||
<service name="File_system"> <child name="vfs"/> </service>
|
<service name="File_system"> <child name="vfs"/> </service>
|
||||||
<service name="ROM" label_last="bash"> <child name="vfs_rom"/> </service>
|
|
||||||
<service name="ROM" label_suffix=".lib.so"> <parent/> </service>
|
<service name="ROM" label_suffix=".lib.so"> <parent/> </service>
|
||||||
<service name="ROM" label_prefix=""> <child name="vfs_rom"/> </service>
|
<service name="ROM" label_last="/bin/bash"> <child name="vfs_rom"/> </service>
|
||||||
|
<service name="ROM" label_prefix="/bin"> <child name="vfs_rom"/> </service>
|
||||||
<any-service> <parent/> <any-child/> </any-service>
|
<any-service> <parent/> <any-child/> </any-service>
|
||||||
</route>
|
</route>
|
||||||
</start>
|
</start>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user