View previous topic :: View next topic |
Author |
Message |
M.A. Apprentice
Joined: 21 Mar 2003 Posts: 168 Location: /home/España/Valencia
|
Posted: Fri May 09, 2003 6:18 pm Post subject: C programming: errno msg: Bad adress *SOLVED* (argv stuff) |
|
|
I am programming a little suid program that makes a call using execv, but this call is not succesful and the error I get is: Bad addres (errno is set to EFAULT). I don't know why this error is produced, I have correctly set the path to the program and the args vector (indeed I print them out to see if they are correctly set). Could you give me any clue?
Thanks.
[edit]
From the manual page of execve:
Code: |
EFAULT filename points outside your accessible address space.
|
I don't know what this mean in the context I'm moving.
[/edit]
Last edited by M.A. on Sat May 10, 2003 10:51 am; edited 1 time in total |
|
Back to top |
|
|
MathFreak Apprentice
Joined: 07 Jul 2002 Posts: 217 Location: Bethlehem, PA
|
Posted: Fri May 09, 2003 7:04 pm Post subject: |
|
|
Without the code it's hard to say. What exactly are you doing with argv? As far as I know, EFAULT happens when you do a syscall with a pointer that points to something you're not allowed to access. |
|
Back to top |
|
|
M.A. Apprentice
Joined: 21 Mar 2003 Posts: 168 Location: /home/España/Valencia
|
Posted: Fri May 09, 2003 8:54 pm Post subject: |
|
|
Well, it's a very simple program. What I want is to allow users to change their ftp password for pureftpd. I hope this little program to be secure enough, but it simply doesn't work. Here is the code:
Code: |
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define INVALID_ARGC 1
#define OPTIONS_NOT_ALLOWED 2
#define NOT_OWNER 3
extern int errno;
int main(int argc, char *argv[])
{
FILE *passarch;
struct passwd *ftp_user;
int mine;
char *args[3];
/* The following functions show usage and errors respectively.
I don't provide the code as it's unrelevant... */
void uso(char *);
void error(int);
const char *passfich = "/etc/pureftpd.passwd";
const char *purepw = "/usr/bin/pure-pw";
args[0] = "passwd";
args[2] = "-m";
if (argc!=2)
{
error(INVALID_ARGC);
uso(argv[0]); exit(1);
}
if (!strncmp("-",argv[1],1))
{
error(OPTIONS_NOT_ALLOWED);
uso(argv[0]); exit(1);
}
mine = 0;
passarch = fopen(passfich, "r");
while(ftp_user = fgetpwent(passarch))
if (!strcmp(ftp_user->pw_name,argv[1]))
{
if (ftp_user->pw_uid==getuid()) mine = 1;
break;
}
if (!mine) {error(NOT_OWNER); exit(1);}
args[1] = argv[1];
/* This lines are for testing if the args are correctly set
printf("%s ",purepw);
for (mine=0;mine<3;mine++) printf("%s ", args[mine]);
printf("\n");
*/
if (execv(purepw, args))
fprintf(stderr, strerror(errno));
}
|
See those two last lines of code.
Thanks for your help. |
|
Back to top |
|
|
idl Retired Dev
Joined: 24 Dec 2002 Posts: 1728 Location: Nottingham, UK
|
Posted: Fri May 09, 2003 9:03 pm Post subject: |
|
|
ok.. i'm a noob C programmer so this is probably wrong.. but to me it looks like it should be:
Code: | if (!execv(purepw, args))
fprintf(stderr, strerror(errno)); |
_________________ a.k.a port001
Found a bug? Please report it: Gentoo Bugzilla |
|
Back to top |
|
|
M.A. Apprentice
Joined: 21 Mar 2003 Posts: 168 Location: /home/España/Valencia
|
Posted: Fri May 09, 2003 9:14 pm Post subject: |
|
|
No, it isn't. execv doesn't return if it has success because the program you are running is replaced with that one called by execv. It only returns if it hasn't success. In fact, this code does the same:
Code: |
execv(purepw, args);
fprintf(stderr, strerror(errno));
|
But thank you anyway. |
|
Back to top |
|
|
idl Retired Dev
Joined: 24 Dec 2002 Posts: 1728 Location: Nottingham, UK
|
Posted: Fri May 09, 2003 9:21 pm Post subject: |
|
|
M.A. wrote: | No, it isn't. execv doesn't return if it has success because the program you are running is replaced with that one called by execv. It only returns if it hasn't success. In fact, this code does the same:
Code: |
execv(purepw, args);
fprintf(stderr, strerror(errno));
|
But thank you anyway. |
ok my bad
Perhaps its connected the to changes made in glibc 2.3.2 with errno?
EDIT: Done a little research and it may infact be your problem... (if your running glibc 2.3.2)
Try removing 'extern int errno;'
http://archive.linuxfromscratch.org/mail-archives/lfs-dev/2003/03/0054.html _________________ a.k.a port001
Found a bug? Please report it: Gentoo Bugzilla |
|
Back to top |
|
|
M.A. Apprentice
Joined: 21 Mar 2003 Posts: 168 Location: /home/España/Valencia
|
Posted: Sat May 10, 2003 1:46 am Post subject: |
|
|
I really appreciate your effort, thank you. But the problem is still there. I don't use glibc 2.3.2, and moreover, the problem is the same even when I don't use errno. Now I'm gonna to test what happens if I don't use const char. Maybe it's stupid, but as the error is that I cannot use some adress, maybe it has to do with the protected memory allocated by const char... |
|
Back to top |
|
|
() l33t
Joined: 25 Nov 2002 Posts: 610
|
Posted: Sat May 10, 2003 8:09 am Post subject: |
|
|
Don't know if this has anything to do with it, but according to the execv manpage the argv array needs to be zero-terminated. |
|
Back to top |
|
|
EnricoHorn Apprentice
Joined: 23 Apr 2003 Posts: 165 Location: Koenigsee, Thuringia, Germany
|
Posted: Sat May 10, 2003 8:32 am Post subject: |
|
|
Code: |
args[0] = "passwd";
args[2] = "-m";
|
I think, you should do it this way:
Code: |
args[0] = malloc(7);
sprintf(args[0],"passwd");
args[2] = malloc(4);
sprintf(args[2],"-rn");
|
So the strings are correctly allocated and zero-terminated. |
|
Back to top |
|
|
() l33t
Joined: 25 Nov 2002 Posts: 610
|
Posted: Sat May 10, 2003 9:46 am Post subject: |
|
|
EnricoHorn wrote: | Code: |
args[0] = "passwd";
args[2] = "-m";
|
I think, you should do it this way:
Code: |
args[0] = malloc(7);
sprintf(args[0],"passwd");
args[2] = malloc(4);
sprintf(args[2],"-rn");
|
So the strings are correctly allocated and zero-terminated. |
No no, shouldn't be any problem at all. The compiler should allocate and assign strings for him, the problem lies elsewhere. execv needs to be presented with a zero-terminated array of arguments. The *argv* (as in the argv parameter of the execv function) array should be zero terminated, since it has no other way of knowing the number of arguments. |
|
Back to top |
|
|
M.A. Apprentice
Joined: 21 Mar 2003 Posts: 168 Location: /home/España/Valencia
|
Posted: Sat May 10, 2003 10:48 am Post subject: |
|
|
Problem solved
I was misusing the args[] to pass to execv. The first element must be the name of the executable, and the array has to be zero terminated (thank you EnricoHorn and (), your comments give me the idea). So the code now works and the differences:
Code: |
char *args[5];
...
args[0] = "pure-pw";
args[1] = "passwd";
args[3] = "-m";
args[4] = 0;
...
args[2] = argv[1];
|
The rest remains exactly the same, and it works (now my users are able to change their ftp password, I'm gonna use crypt() now to ensure they don't use the same password in ftp than in the system).
Thank you all for your comments and help! |
|
Back to top |
|
|
() l33t
Joined: 25 Nov 2002 Posts: 610
|
Posted: Sat May 10, 2003 11:01 am Post subject: |
|
|
Cheers :] |
|
Back to top |
|
|
|