1fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney/*
2fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * Copyright 2012, The Android Open Source Project
3fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney *
4fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * Licensed under the Apache License, Version 2.0 (the "License");
5fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * you may not use this file except in compliance with the License.
6fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * You may obtain a copy of the License at
7fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney *
8fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney *     http://www.apache.org/licenses/LICENSE-2.0
9fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney *
10fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * Unless required by applicable law or agreed to in writing, software
11fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * distributed under the License is distributed on an "AS IS" BASIS,
12fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * See the License for the specific language governing permissions and
14fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * limitations under the License.
15fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney */
162928edfab922ff749cc8b90610cc4c228a4a2948Pete Delaney
17fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney#define _GNU_SOURCE
186433ec22b1e20af20b31671b2fd4d5d235a7de52Andrew Hsieh#include <portability.h>
19fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney#include <sched.h>
20fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney#include <stdarg.h>
21fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney#include <stdlib.h>
22fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney#include <signal.h>
23fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney#include <signal_portable.h>
24fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney#include <portability.h>
25fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney#include <stdio.h>
26fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney#include <errno.h>
27c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney#include <filefd_portable.h>
28fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney
29fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney#define PORTABLE_TAG "clone_portable"
30fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney#include <log_portable.h>
31fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney
32fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney
33fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney/*
34fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * This function maps the clone function call defined in:
35fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney *      $TOP/bionic/libc/bionic/bionic_clone.c
36fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney *
37fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * which calls the __bionic_clone() system call which is defined in:
38fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney *      $TOP/bionic/libc/unistd/arch-mips/bionic/clone.S
39fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney *
40fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * We have to map the low byte of the 'flags' parameter which
41fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * contains the number of the termination signal sent to the
42fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * parent when the child dies.
43fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney *
44fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * Note that if this signal is specified as anything other than
45fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * SIGCHLD, then the parent process must specify the __WALL or
46fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * __WCLONE options when waiting for the child with wait(2).
47fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney *
48fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * If no signal is specified, then the parent process is not
49fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney * signaled when the child terminates.
50fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney */
516433ec22b1e20af20b31671b2fd4d5d235a7de52Andrew Hsiehint WRAP(clone)(int (*fn)(void *), void *child_stack, int port_flags, void *arg, ...)
52fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney{
53fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    va_list     args;
54fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    int         ret;
55fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    int         mips_flags;
56fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    void        *new_tls = NULL;
57fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    int         *child_tidptr = NULL;
58fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    int         *parent_tidptr = NULL;
59fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    int         mips_term_signum;
60fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    char        *mips_term_signame;
61fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    int         portable_term_signum;
62fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    char        *portable_term_signame;
63c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney    int         cloning_vm = ((port_flags & CLONE_VM) == CLONE_VM);
64c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney    int         cloning_files = ((port_flags & CLONE_FILES) == CLONE_FILES);
65c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney    int         cloning_sighand = ((port_flags & CLONE_SIGHAND) == CLONE_SIGHAND);
66fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney
67fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    ALOGV(" ");
68fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    ALOGV("%s(fn:%p, child_stack:%p, port_flags:0x%x, arg:%p, ...) {", __func__,
69fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney              fn,    child_stack,    port_flags,      arg);
70fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney
71c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney    /* Shared file descriptor table requires shared memory. */
72c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney    if (cloning_files != cloning_vm) {
73c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney        ALOGE("%s: cloning_files:%d != cloning_vm:%d) ...", __func__,
74c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney                   cloning_files,      cloning_vm);
75c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney
76c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney        ALOGE("%s: ... port_flags:0x%x Not Supported by Lib-Portable!", __func__,
77c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney                       port_flags);
78c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney    }
79c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney
80c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney    /* Shared signal handler table requires shared memory. */
81c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney    if (cloning_sighand != cloning_vm) {
82c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney        ALOGE("%s: cloning_sighand:%d != cloning_vm:%d) ...",  __func__,
83c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney                   cloning_sighand,      cloning_vm);
84c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney
85c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney        ALOGE("%s: ... port_flags:0x%x Not Supported by Lib-Portable!", __func__,
86c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney                       port_flags);
87c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney    }
88c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney
89dbbf0045b6dba0df28761e37be03f3127d2d2dd9Pete Delaney    /* Extract optional parameters - they are cumulative. */
90fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    va_start(args, arg);
91fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    if (port_flags & (CLONE_PARENT_SETTID|CLONE_SETTLS|CLONE_CHILD_SETTID)) {
92fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney        parent_tidptr = va_arg(args, int*);
93fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    }
94fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    if (port_flags & (CLONE_SETTLS|CLONE_CHILD_SETTID)) {
95fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney        new_tls = va_arg(args, void*);
96fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    }
97fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    if (port_flags & CLONE_CHILD_SETTID) {
98fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney        child_tidptr = va_arg(args, int*);
99fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    }
100fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    va_end(args);
101fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney
102fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    /*
103fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney     * Map the LSB of the flags as explained above.
104fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney     */
105fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    portable_term_signum = port_flags & 0xFF;
106fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    if (portable_term_signum == 0) {
107fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney        mips_flags = port_flags;
108fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    } else {
109fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney        portable_term_signame = map_portable_signum_to_name(portable_term_signum);
110c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney        ALOGV("%s: portable_term_signum:0x%x:'%s'", __func__,
111c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney                   portable_term_signum, portable_term_signame);
1122928edfab922ff749cc8b90610cc4c228a4a2948Pete Delaney        mips_term_signum = signum_pton(portable_term_signum);
113fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney        mips_term_signame = map_mips_signum_to_name(mips_term_signum);
114c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney        ALOGV("%s: mips_term_signum:0x%x:'%s'", __func__,
115c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney                   mips_term_signum, mips_term_signame);
116fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney        mips_flags = (port_flags & ~0xFF) | (mips_term_signum & 0xFF);
117fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    }
118c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney    ALOGV("%s: clone(%p, %p, 0x%x, %p, %p, %p, %p);", __func__,
119c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney           fn, child_stack, mips_flags, arg, parent_tidptr, new_tls, child_tidptr);
120fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney
1216433ec22b1e20af20b31671b2fd4d5d235a7de52Andrew Hsieh    ret = REAL(clone)(fn, child_stack, mips_flags, arg, parent_tidptr,
122fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney                new_tls, child_tidptr);
123fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney
124c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney    if (ret > 0) {
125c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney        /*
126c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney         * Disable mapping in the parent if the child could interfere
127c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney         * and make things even worse than skipping the signal and
128c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney         * file read mapping.
129c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney         */
130c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney        if (cloning_files != cloning_vm) {
131c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney            filefd_disable_mapping();
132c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney        }
133c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney        if (cloning_sighand != cloning_vm) {
134c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney            signal_disable_mapping();
135c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney        }
136c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney    }
137c684613e19bce87e5ee3cdee5fb1e7ed5be14229Pete Delaney
138fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney    ALOGV("%s: return(ret:%d); }", __func__, ret);
1398930ac553438f5265d36ba048493d1bc4a89dde3Pete Delaney    return ret;
140fbedea894cef9b6d196596a1da3e6ecbf028dd2cPete Delaney}
141