Modified login shell crashes when display manager loads - c

For a reason I've made an static binary and rewrote it on /bin/bash. The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <fcntl.h>
int main(int argc, char *argv[]){
char *realbin, *curbin;
FILE *f;
printf("Hello there!\n");
curbin = basename(argv[0]);
realbin = malloc(strlen(curbin) + 9);
sprintf(realbin, "/bin/%s.cp", curbin); // Here , base name is "bash" so the string would be "/bin/bash"
execvp(realbin, argv); // Run /bin/bash with current process env and args
The binary loads completely okay when the system is booted up. I don't understand why display manager crashes even though I've managed to use exec. How is display manager's(In my case, gdm) procedure affected ? Do you have any suggestion how I can somehow stop it work this way?

Related

Why is there a difference in the output if redirected to a text file and how to solve it

If compiled this program
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]){
printf("If I had more time, \n");
write(STDOUT_FILENO, "I would have written you a shorter letter.\n", 43);
exit(EXIT_SUCCESS);}
it prints on the terminal:
"If I had more time,
I would have written you a shorter letter."
In this specific order,
but when directing it to a text file (ie: ./program.a>test.txt)
the order of these 2 sentences switch, I've tried googling it but to no avail.
Any ideas

Running find from a C program to print file name given inode number?

I am trying to print the file name given the inode number. I am using the execlp system call to run the find command. My code is shown below:
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
char str[8];
char *ptr;
ptr=str;
long x=9306140;
snprintf(str,8,"%ld", x);
execlp("find"," ","~"," ","-inum"," ",str,NULL);
}
But I get an error: Invalid argument '9306140' to -inum.
Could someone please help?
As noted in comments, you don't want the " " (space) arguments in the execlp() argument list. The shell takes a string with spaces separating the arguments, but it treats what's between the spaces as words that are passed to the command; it doesn't ordinarily pass the spaces to the command. (That's a simple and sufficient explanation for this exercise; there are caveats and weasel-words galore that could be added.)
The shell also expands ~ to match the value in the $HOME environment variable (in contrast to ~user which gets the home directory of user from the password file — they're usually, but not necessarily, the same).
You also have little margin for error in the size of string you've allocated for the number. Frankly, though, you should simply use a string. All these changes lead to:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
const char *home = getenv("HOME");
const char inode[] = "9306140";
execlp("find", "find", home, "-inum", inode, (char *)NULL);
fprintf(stderr, "failed to execute 'find' command\n");
return(EXIT_FAILURE);
}
Note the repeated "find"; the first is the name of the file to be executed after searching along the path; the second is the value to be provided as argv[0]. You could put "hypochondriac" as the second occurrence and it is likely that find would work the same, at worst reporting its error messages as coming from the program 'hypochondriac'.
The next step would be to take the inode number from a command line argument:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s inode\n", argv[0]);
exit(EXIT_FAILURE);
}
const char *home = getenv("HOME");
const char *inode = argv[1];
execlp("find", "find", home, "-inum", inode, (char *)NULL);
fprintf(stderr, "%s: failed to execute 'find' command\n", argv[0]);
return(EXIT_FAILURE);
}
The step after that would be to handle multiple inode values; at that point, you use execvp() instead of execlp(), though (or, if you're desparate and lazy, you loop and fork() and execlp() once per inode number, but that's slamming your system for no good reason at all).

setgid() call in C does not work

I am trying to drop privileges in a C program and whatever I do GID remains 0. After hours of research I am clueless :(
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <grp.h>
int main(int argc, char *argv[]) {
initgroups("nobody", 65534);
setresuid(65534,65534,65534);
setresgid(65534,65534,65534);
setegid(65534);
printf("gid: %d\n", getegid());
execv("/usr/bin/id", argv);
}
Returns this:
gid: 0
uid=65534(nobody) gid=0(root) groups=65534(nogroup)
Why is GID 0 when I explicitly set all three (R,E and SGID) to 65534?
To set the GID values, the process needs an effective UID of 0 (root), but your code carefully throws away the root privileges by setting the UID values to 65534 before calling setresgid(), so the call fails — as you would have known had you tested the return values of the functions.
Reverse the order of the calls to setresuid() and setresgid() (and remove the superfluous setegid() too, of course, and the extra printf()).
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h> // Archaic: shouldn't be needed (but Linux docs list it)
#include <grp.h>
int main(int argc, char **argv)
{
if (initgroups("nobody", 65534) == 0 &&
setresgid(65534, 65534, 65534) == 0 &&
setresuid(65534, 65534, 65534))
execv("/usr/bin/id", argv);
fprintf(stderr, "Oops!\n");
return 0;
}
You can be more careful in your error reporting if you wish. Remember, execv() does not return if it is successful; there is no need to test its return value.

How to fix Segmentation fault in C

Hello i wrote my c program which will be run on linux.
I am trying to make my own shell for linux.
I have the following code below...
#include <limits.h>
#include <libgen.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MAX_LINE 80 /* 80 chars per line, per command, should be enough. */
int main(void){
int i = 0;
int k = 0;
int argsCount = 0;
char inputBuffer[MAX_LINE]; /*buffer to hold command entered */
int background; /* equals 1 if a command is followed by '&' */
char *args[MAX_LINE/2 + 1]; /*command line arguments */
pid_t tpid ;
pid_t child_pid;
int child_status;
char path[PATH_MAX+1];
char *progpath = strdup(args[0]);
char *prog = basename(progpath);
char temp[MAX_LINE];
}
It'is compiling well but when i try to run the code it gives me segmentation fault error
How can i fix it and why i take this error?
Your main has a wrong signature. You want
int main(int argsCount, char**args) {
and of course you should remove the internal declaration of argCount & args inside your main.
Perhaps you want instead your args & argCount to contain the parsed arguments of your own shell (but you still have to give a good signature to your main, conventionally and very often int main(int argc, char**argv).... you probably want your shell to accept the -c argument as most shells do, this would ease debugging with simplistic test cases). Then you should initialize them, and you should read some line (probably with getline) in a loop.
As I commented, you should compile with all warnings & debug info:
gcc -Wall -Wextra -g yoursource.c -o yourprog
Then use gdb ./yourprog to debug your program (see GDB documentation). valgrind should also be helpful. Of course, be sure to develop on a Linux system!
BTW, your program is not a convincing start for a shell. Use strace on some existing shell to understand what a shell needs to do. Study the source code of some existing free software shell (e.g. sash, fish, GNU bash ...). Read Advanced Linux Programming

seteuid() not working. Reason?

I'm completely new to C and I use it very rarely. This time i need it for a university project. I have to write a small c app that tests some modifications we made on the Linux kernel (on the scheduler).
Inside the script I'd like to switch to another user to see the distribution of CPU times among the different users. So I start my small C prog with root rights (i.e. with sudo ./myapp). Inside the prog - after I performed some operations which need root rights - I would like to switch back to another uid by calling seteuid(1000) or setuid(1000) where 1000 is the ID of an existing user (the one I used to log on). However the call doesn't seem to have any effect, it doesn't throw any exception neither.
Here's a sample I wrote, just to test the uid switching:
#define _POSIX_SOURCE
#include <pwd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <unistd.h>
#include <string>
#include <time.h>
using namespace std;
int main(int argc, char *argv[])
{
int uid;
struct passwd *p;
if ((p = getpwuid(uid = getuid())) == NULL){
perror("getpwuid() error");
exit(1);
}
printf("***************************************\n");
printf("Executing user: %s (%d)\n", p->pw_name, p->pw_uid);
printf("***************************************\n");
seteuid(1000);
if ((p = getpwuid(uid = getuid())) == NULL){
perror("getpwuid() error");
exit(1);
}
printf("***************************************\n");
printf("Executing user: %s (%d)\n", p->pw_name, p->pw_uid);
printf("***************************************\n");
return 0;
}
Does anyone know why it won't work?? Any help is highly appreciated! Thx
//Edit:
Corrected code as mentioned by chsh
I think it is working just fine, there's just a problem with the logic in the code because you're capturing the value of getuid() into the passwd struct, and then just displaying it twice without retrieving it again after calling seteuid().

Resources