Why I cant create raw socket in Ubuntu? - c

I'm learning how to work with raw sockets in Linux. I'm trying to create a socket like that:
if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
perror("socket() failed");
exit(-1);
}
But all I got after launch is:
socket() failed: Operation not permitted
I know that only root can create raw sockets, but if I run it with SUID bit or sudo - the
problem is the same. What's wrong? The system is Ubuntu 11.04.
Maybe I'm including needless headers?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
And I'm wondering - why SUID is useless?

My money on you not running your code correctly.
I've copied and pasted your exact code into an empty main(). I get the same error if I run it as myself, but it runs correctly under sudo. This is on Ubuntu.
The code:
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
int sd;
if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
perror("socket() failed");
return -1;
}
return 0;
}
Run as myself:
aix#aix:~$ ./a.out
socket() failed: Operation not permitted
aix#aix:~$
Run as root:
aix#aix:~$ sudo ./a.out
aix#aix:~$

according to man: Only processes with an effective user ID of 0 or the CAP_NET_RAW capability are allowed to open raw sockets
So you could run you application with sudo as was suggested below or set CAP_NET_RAW capability to it (actually you'll need CAP_NET_ADMIN too):
# setcap cap_net_raw,cap_net_admin=eip PATH_TO_YOUR_APPLICATION
Details could be found at http://ftp.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.4/capfaq-0.2.txt

Header will not affect it in anyway.
Even if you would be adding some more unnecessary files it will not affect the working of the program.

Related

Why after load seccomp filter, PING will no work by normal user

I use seccomp record 'ping' used syscall. When I run it, it always notice
socket: Operation not permitted.
I can run ping in bash very well, but no work after load seccomp filter in program.
But if I run the same program by root, it will run very well.
This is running in Ubuntu 18.04 with 4.15.0-54-generic kernel.
I have tried use Root user to run the program, then in the child progress, I use setuid(1000) to set to a normal user, and it still no work.
If I not use fork, it still notice no premitted.
If I change the seccomp default action to SCMP_ACT_ALLOW, it still no work too.
Here is a simple code by C.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <signal.h>
#include <seccomp.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/wait.h>
void child() {
setuid(1000);
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_LOG);
if (seccomp_load(ctx) != 0) {
printf("SCMP LAOD ERR!");
} else {
seccomp_release(ctx);
}
execl("/bin/ping", "ping", "-c", "1", "172.16.1.1", NULL);
printf("EXEC FAIL");
}
int main(){
int p = fork();
if (p < 0) {
printf("Frok ERROR!");
exit(1);
}
if ( p == 0 ) {
child();
} else {
struct rusage usage;
int status;
if (wait4(p, &status, WSTOPPED, &usage) == -1) {
kill(p, SIGKILL);
}
}
}
I use gcc main.c -o main.out -lseccomp to compile it.
English is not my first Language, I'm sorry about my grammar.
ping only works as root. Normally it runs as root because it has the setuid bit set in its file permissions:
-rwsr-xr-x 1 root root 44168 May 8 2014 /bin/ping
^ ^^^^
|
this 's' is called 'setuid' and means it wants to run as the user which owns it, which is root
You cannot use seccomp unless you are root, or you set the no_new_privs flag. You are not using seccomp directly, but through a library. It appears the library is setting the flag for you.
The no_new_privs flag means that you cannot run setuid programs. Well, you can run them, but they won't be setuid. They'll run as your user. Which doesn't have permission to send special packets the way ping requires. So ping fails because it doesn't have permission to ping.

C Socket Bind Failed with the Error: Operation not permitted [duplicate]

I'm newbee and just making my first steps in c++ under linux.
So I have some task about sockets. I'm following guides, especially this one. And code examples are not working. I started with this:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCK_PATH "echo_socket"
int main(void)
{
int s, s2, t, len;
struct sockaddr_un local, remote;
char str[100];
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(s, (struct sockaddr *)&local, len) == -1) {
perror("bind");
exit(1);
}
return 0;
}
I've figured out that to compile it (Code::Blocks) there must be one more include:
#include <unistd.h>
But after successful run I'm getting message "Bind: Operation not permitted". What is wrong? I've tried to run it under root and still it is not working.
Some Unix systems won't allow you to create sockets everywhere. Make sure you have the right permissions and the right file system underneath. (Fat32 as it is used on sdcards in mobile phones won't allow additional flags to files and might get you into trouble)
Finally on newer systems there are security things running like selinux which might block the creation of sockets.
On my example I had to change
#define SOCK_PATH "echo_socket"
to
#define SOCK_PATH "/dev/socket/echo_socket"
after that it worked immediately. (executable started in root shell)
Because of no permission.
You can
#define SOCK_PATH "/home/username/echo_socket"
and it will run normally.

socket creation return -1 (Operation not permitted) [duplicate]

I'm learning how to work with raw sockets in Linux. I'm trying to create a socket like that:
if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
perror("socket() failed");
exit(-1);
}
But all I got after launch is:
socket() failed: Operation not permitted
I know that only root can create raw sockets, but if I run it with SUID bit or sudo - the
problem is the same. What's wrong? The system is Ubuntu 11.04.
Maybe I'm including needless headers?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
And I'm wondering - why SUID is useless?
My money on you not running your code correctly.
I've copied and pasted your exact code into an empty main(). I get the same error if I run it as myself, but it runs correctly under sudo. This is on Ubuntu.
The code:
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
int sd;
if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
perror("socket() failed");
return -1;
}
return 0;
}
Run as myself:
aix#aix:~$ ./a.out
socket() failed: Operation not permitted
aix#aix:~$
Run as root:
aix#aix:~$ sudo ./a.out
aix#aix:~$
according to man: Only processes with an effective user ID of 0 or the CAP_NET_RAW capability are allowed to open raw sockets
So you could run you application with sudo as was suggested below or set CAP_NET_RAW capability to it (actually you'll need CAP_NET_ADMIN too):
# setcap cap_net_raw,cap_net_admin=eip PATH_TO_YOUR_APPLICATION
Details could be found at http://ftp.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.4/capfaq-0.2.txt
Header will not affect it in anyway.
Even if you would be adding some more unnecessary files it will not affect the working of the program.

Loopback example using INADDR_LOOPBACK does not work

I am trying to set a loopback socket in C but nothing works. I'm trying to make a function that opens a socket with the loopback address ,send data to socket and from another function read the data but nothing works. I believe that I don't know how to use the functions related to connections. Here is what I accomplished so far:
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
#include <iostream>
#include <cerrno>
#include <pthread.h>
int internal_s;
void function1(){
if ((internal_s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror_exit("socket");
/* Find server address */
struct sockaddr_in loopback;
struct sockaddr *serverptr = (struct sockaddr*)&loopback;
/*Convert port number to integer*/
loopback.sin_family = AF_INET; /* Internet domain */
loopback.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
loopback.sin_port=htons(10000);
/* Initiate connection */
if (bind(internal_s,serverptr, sizeof(loopback))<0)
perro("bind");
int test=1;
err=write(internal_s,&test,sizeof(int));
if(err<0)
perror(write);
}
void Open_Internal_sock(int socket_s){
struct sockaddr_in loopback;
struct sockaddr *serverptr = (struct sockaddr*)&loopback;
/*Convert port number to integer*/
loopback.sin_family = AF_INET; /* Internet domain */
loopback.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
loopback.sin_port=htons(10000);
/* Initiate connection */
if (bind(socket_s,serverptr, sizeof(loopback))<0)
perror("bind");//Invalid argument
int test;
if(read(socket_s,&test,sizeof(int))<0)
perror("read");//herer it prints:Transport endpoint is not connected
}
int main(){
function1(i);
Open_Internal_sock(internal_s);
}
In short, the client(sender, "writer") needs to call connect() and the server(listener, receiver, "reader") needs to cal listen() and accept().
The server and client also need separate threads of execution, because some of the socket operations block and would cause a single thread of execution to stop forever. Easiest is probably to make a server.c and client.c as separate programs.
Additionally, try compiling your code with warnings enabled, e.g., gcc -Wall . There are now quite many errors, which the compiler can point out for you. For clearer messages, try clang instead of gcc as a compiler.
I suggest looking at http://kohala.com/start/unpv12e/unpv12e.tar.gz . Unpack with tar xzvf unpv12e.tar.gz and look at unpv12e/tcpcliserv/tcpcli01.c and unpv12e/tcpcliserv/tcpserv01.c . In case you are tempted to copy&paste, notice that the Capital letters in, e.g., Listen() need to be changed to lower case for the code to work without unpv headers. This change also removes all checks for errors, so put in your own error handling.

How do I find the MAC address programatically on IRIX?

How do I find the MAC address of a network card on IRIX? I'd rather not shell out to something that displays it and parse the output.
I'm coding C.
Methods that require root access are acceptable.
#include <net/raw.h>
#include <net/if.h>
#include <net/soioctl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
...
struct ifreq ifdat;
int s;
s = socket (PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
strcpy (ifdat.ifr_name, "en0");
ioctl (s, SIOCGIFADDR, &ifdat);
...
Clean it up a little, and ifdat should contain your MAC address.
I don't know about programmatically, but you could try /etc/nvram eaddr, I suppose you could exec() that.
On some platforms (Linux, for example) ioctl() allows to obtain MAC address. You need to check on IRIX as ioctl() is platform-dependent.

Resources