Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
743c4f55
Commit
743c4f55
authored
Apr 15, 2017
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix various issues
parent
a92c9fc2
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
131 additions
and
63 deletions
+131
-63
misc.c
misc.c
+13
-0
su.h
su.h
+1
-0
su_client.c
su_client.c
+117
-63
No files found.
misc.c
View file @
743c4f55
...
@@ -8,6 +8,7 @@
...
@@ -8,6 +8,7 @@
#include <signal.h>
#include <signal.h>
#include <unistd.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "magisk.h"
#include "magisk.h"
#include "su.h"
#include "su.h"
...
@@ -52,3 +53,15 @@ char *get_command(const struct su_request *to) {
...
@@ -52,3 +53,15 @@ char *get_command(const struct su_request *to) {
return
DEFAULT_SHELL
;
return
DEFAULT_SHELL
;
}
}
int
fork_zero_fucks
()
{
int
pid
=
fork
();
if
(
pid
)
{
int
status
;
waitpid
(
pid
,
&
status
,
0
);
return
pid
;
}
else
{
if
(
fork
()
!=
0
)
exit
(
0
);
return
0
;
}
}
su.h
View file @
743c4f55
...
@@ -130,5 +130,6 @@ policy_t database_check(struct su_context *ctx);
...
@@ -130,5 +130,6 @@ policy_t database_check(struct su_context *ctx);
void
setup_sighandlers
(
void
(
*
handler
)(
int
));
void
setup_sighandlers
(
void
(
*
handler
)(
int
));
void
set_identity
(
unsigned
uid
);
void
set_identity
(
unsigned
uid
);
char
*
get_command
(
const
struct
su_request
*
to
);
char
*
get_command
(
const
struct
su_request
*
to
);
int
fork_zero_fucks
();
#endif
#endif
su_client.c
View file @
743c4f55
...
@@ -20,31 +20,12 @@
...
@@ -20,31 +20,12 @@
#include "su.h"
#include "su.h"
#include "pts.h"
#include "pts.h"
int
from_uid
,
from_pid
;
// Constants for the atty bitfield
#define ATTY_IN 1
struct
su_daemon_info
{
#define ATTY_OUT 2
int
child
;
#define ATTY_ERR 4
int
client
;
};
static
void
*
wait_result
(
void
*
args
)
{
struct
su_daemon_info
*
info
=
args
;
LOGD
(
"su: wait_result waiting for %d
\n
"
,
info
->
child
);
err_handler
=
exit_thread
;
int
status
,
code
;
if
(
waitpid
(
info
->
child
,
&
status
,
0
)
>
0
)
code
=
WEXITSTATUS
(
status
);
else
code
=
-
1
;
// Pass the return code back to the client
int
from_uid
,
from_pid
;
write_int
(
info
->
client
,
code
);
LOGD
(
"su: return code to client: %d
\n
"
,
code
);
close
(
info
->
client
);
free
(
info
);
return
NULL
;
}
static
void
sighandler
(
int
sig
)
{
static
void
sighandler
(
int
sig
)
{
restore_stdin
();
restore_stdin
();
...
@@ -71,27 +52,46 @@ static void sighandler(int sig) {
...
@@ -71,27 +52,46 @@ static void sighandler(int sig) {
void
su_daemon_receiver
(
int
client
)
{
void
su_daemon_receiver
(
int
client
)
{
LOGD
(
"su: get request
\n
"
);
LOGD
(
"su: get request
\n
"
);
if
(
fork_zero_fucks
())
{
// Root daemon
close
(
client
);
return
;
}
// Set the error handler back to normal
err_handler
=
exit_proc
;
// Fork a new process, the child process will need to setsid,
// Fork a new process, the child process will need to setsid,
// open a pseudo-terminal, and will eventually run exec
// open a pseudo-terminal, and will eventually run exec
// The parent process
(the root daemon) will open a new thread to
// The parent process
will wait for the result and
// send the return code back to our client
// send the return code back to our client
int
child
=
fork
();
int
child
=
fork
();
if
(
child
<
0
)
{
if
(
child
<
0
)
{
PLOGE
(
"fork"
);
write
(
client
,
&
child
,
sizeof
(
child
));
write
(
client
,
&
child
,
sizeof
(
child
));
close
(
client
);
close
(
client
);
PLOGE
(
"fork"
);
return
;
return
;
}
else
if
(
child
!=
0
)
{
}
else
if
(
child
!=
0
)
{
pthread_t
wait_thread
;
struct
su_daemon_info
*
info
=
xmalloc
(
sizeof
(
*
info
));
// Wait result
info
->
client
=
client
;
LOGD
(
"su: wait_result waiting for %d
\n
"
,
child
);
info
->
child
=
child
;
int
status
,
code
;
// Change to a fancy name
strcpy
(
argv0
,
"magisksu"
);
// In parent, open a new thread to wait for the child to exit,
if
(
waitpid
(
child
,
&
status
,
0
)
>
0
)
// and send the exit code across the wire.
code
=
WEXITSTATUS
(
status
);
xpthread_create
(
&
wait_thread
,
NULL
,
wait_result
,
info
);
else
return
;
code
=
-
1
;
// Pass the return code back to the client
write_int
(
client
,
code
);
LOGD
(
"su: return code to client: %d
\n
"
,
code
);
close
(
client
);
exit
(
code
);
}
}
LOGD
(
"su: child process started
\n
"
);
LOGD
(
"su: child process started
\n
"
);
...
@@ -99,9 +99,6 @@ void su_daemon_receiver(int client) {
...
@@ -99,9 +99,6 @@ void su_daemon_receiver(int client) {
// ack
// ack
write_int
(
client
,
1
);
write_int
(
client
,
1
);
// Here we're in the child
// Set the error handler back to normal
err_handler
=
exit_proc
;
// Become session leader
// Become session leader
xsetsid
();
xsetsid
();
...
@@ -139,33 +136,50 @@ void su_daemon_receiver(int client) {
...
@@ -139,33 +136,50 @@ void su_daemon_receiver(int client) {
char
*
pts_slave
=
read_string
(
client
);
char
*
pts_slave
=
read_string
(
client
);
LOGD
(
"su: pts_slave=[%s]
\n
"
,
pts_slave
);
LOGD
(
"su: pts_slave=[%s]
\n
"
,
pts_slave
);
// The the FDs for each of the streams
int
infd
=
recv_fd
(
client
);
int
outfd
=
recv_fd
(
client
);
int
errfd
=
recv_fd
(
client
);
// We no longer need the access to socket in the child, close it
// We no longer need the access to socket in the child, close it
close
(
client
);
close
(
client
);
if
(
pts_slave
[
0
])
{
//Check pts_slave file is owned by daemon_from_uid
//Check pts_slave file is owned by daemon_from_uid
int
ptsfd
;
struct
stat
stbuf
;
struct
stat
stbuf
;
int
res
=
xstat
(
pts_slave
,
&
stbuf
);
xstat
(
pts_slave
,
&
stbuf
);
//If caller is not root, ensure the owner of pts_slave is the caller
//If caller is not root, ensure the owner of pts_slave is the caller
if
(
stbuf
.
st_uid
!=
credentials
.
uid
&&
credentials
.
uid
!=
0
)
{
if
(
stbuf
.
st_uid
!=
credentials
.
uid
&&
credentials
.
uid
!=
0
)
{
LOGE
(
"
Wrong permission of pts_slave"
);
LOGE
(
"su:
Wrong permission of pts_slave"
);
exit
(
1
);
exit
(
1
);
}
}
// Opening the TTY has to occur after the
// Opening the TTY has to occur after the
// fork() and setsid() so that it becomes
// fork() and setsid() so that it becomes
// our controlling TTY and not the daemon's
// our controlling TTY and not the daemon's
ptsfd
=
xopen
(
pts_slave
,
O_RDWR
);
int
ptsfd
=
xopen
(
pts_slave
,
O_RDWR
);
if
(
infd
<
0
)
{
LOGD
(
"su: stdin using PTY"
);
infd
=
ptsfd
;
}
if
(
outfd
<
0
)
{
LOGD
(
"su: stdout using PTY"
);
outfd
=
ptsfd
;
}
if
(
errfd
<
0
)
{
LOGD
(
"su: stderr using PTY"
);
errfd
=
ptsfd
;
}
}
free
(
pts_slave
);
free
(
pts_slave
);
// Swap out stdin, stdout, stderr
// Swap out stdin, stdout, stderr
xdup2
(
ptsfd
,
STDIN_FILENO
);
xdup2
(
infd
,
STDIN_FILENO
);
xdup2
(
ptsfd
,
STDOUT_FILENO
);
xdup2
(
outfd
,
STDOUT_FILENO
);
xdup2
(
ptsfd
,
STDERR_FILENO
);
xdup2
(
errfd
,
STDERR_FILENO
);
close
(
ptsfd
);
su_daemon_main
(
argc
,
argv
);
su_daemon_main
(
argc
,
argv
);
}
}
...
@@ -195,19 +209,59 @@ int su_client_main(int argc, char *argv[]) {
...
@@ -195,19 +209,59 @@ int su_client_main(int argc, char *argv[]) {
getcwd
(
buffer
,
sizeof
(
buffer
));
getcwd
(
buffer
,
sizeof
(
buffer
));
write_string
(
socketfd
,
buffer
);
write_string
(
socketfd
,
buffer
);
// Determine which one of our streams are attached to a TTY
int
atty
=
0
;
if
(
isatty
(
STDIN_FILENO
))
atty
|=
ATTY_IN
;
if
(
isatty
(
STDOUT_FILENO
))
atty
|=
ATTY_OUT
;
if
(
isatty
(
STDERR_FILENO
))
atty
|=
ATTY_ERR
;
if
(
atty
)
{
// We need a PTY. Get one.
// We need a PTY. Get one.
ptmx
=
pts_open
(
buffer
,
sizeof
(
buffer
));
ptmx
=
pts_open
(
buffer
,
sizeof
(
buffer
));
watch_sigwinch_async
(
STDOUT_FILENO
,
ptmx
);
}
else
{
buffer
[
0
]
=
'\0'
;
}
// Send the slave path to the daemon
// Send the
pts_
slave path to the daemon
write_string
(
socketfd
,
buffer
);
write_string
(
socketfd
,
buffer
);
// Send stdin
if
(
atty
&
ATTY_IN
)
{
// Using PTY
send_fd
(
socketfd
,
-
1
);
}
else
{
send_fd
(
socketfd
,
STDIN_FILENO
);
}
// Send stdout
if
(
atty
&
ATTY_OUT
)
{
// Forward SIGWINCH
watch_sigwinch_async
(
STDOUT_FILENO
,
ptmx
);
// Using PTY
send_fd
(
socketfd
,
-
1
);
}
else
{
send_fd
(
socketfd
,
STDOUT_FILENO
);
}
// Send stderr
if
(
atty
&
ATTY_ERR
)
{
// Using PTY
send_fd
(
socketfd
,
-
1
);
}
else
{
send_fd
(
socketfd
,
STDERR_FILENO
);
}
// Wait for acknowledgement from daemon
// Wait for acknowledgement from daemon
read_int
(
socketfd
);
read_int
(
socketfd
);
if
(
atty
&
ATTY_IN
)
{
setup_sighandlers
(
sighandler
);
setup_sighandlers
(
sighandler
);
pump_stdin_async
(
ptmx
);
pump_stdin_async
(
ptmx
);
}
if
(
atty
&
ATTY_OUT
)
{
pump_stdout_blocking
(
ptmx
);
pump_stdout_blocking
(
ptmx
);
}
// Get the exit code
// Get the exit code
int
code
=
read_int
(
socketfd
);
int
code
=
read_int
(
socketfd
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment