`ioctl` to read and write GPIO: invalid argument - linux-kernel

I'm imitating the gpio-hammer example in Linux source code. I'm using Raspberry Pi 3B+ and want an LED to blink.
Here's what I do:
#include <linux/gpio.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, const char **argv) {
int fd, ret;
struct gpiohandle_request req;
struct gpiohandle_data data;
char *gpio_dev_name = "/dev/gpiochip0";
unsigned int gpio_line = 8;
memset(&data.values, 0, sizeof(data.values));
// open device
fd = open(gpio_dev_name, 0);
if (fd == -1) {
fprintf(stderr, "Failed to open %s, %s\n",
gpio_dev_name, strerror(errno));
}
// request gpio output
req.lineoffsets[0] = gpio_line;
req.flags = GPIOHANDLE_REQUEST_OUTPUT | GPIOHANDLE_REQUEST_ACTIVE_LOW;
strcpy(req.consumer_label, "blink");
req.lines = 1;
memcpy(req.default_values, &data, sizeof(req.default_values));
ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (ret == -1) {
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno));
}
// blink
while (1) {
// read data
ret = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno));
exit(ret);
}
// flip digits
data.values[0] = !data.values[0];
// set data
ret = ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret, strerror(errno));
exit(ret);
}
// delay
sleep(1);
}
}
I can compile the gpio-hammer example on RPi and run it with ./gpio-hammer -n gpiochip0 -o 8. Attached to gpiochip0 line8 is an LED and it blinks.
But my program does not work. It fails with
Failed to issue GPIOHANDLE_GET_LINE_VALUES_IOCTL (-22), Invalid argument
I looked into the implement of gpiolib. The ioctl of gpio line handle returns EINVAL (22) if ioctl cmd is not GPIOHANDLE_GET_LINE_VALUES_IOCTL nor GPIOHANDLE_SET_LINE_VALUES_IOCTL. But that's not the case. What's going wrong?

In linux/gpio.h, the description of struct gpiohandle_request says:
/*
* ...
* #fd: if successful this field will contain a valid anonymous file handle
* after a GPIO_GET_LINEHANDLE_IOCTL operation, zero or negative value
* means error
*/
struct gpiohandle_request {
__u32 lineoffsets[GPIOHANDLES_MAX];
__u32 flags;
__u8 default_values[GPIOHANDLES_MAX];
char consumer_label[32];
__u32 lines;
int fd;
};
When use GPIO_GET_LINEHANDLE_IOCTL, the file handle of GPIO chip device is passed through the first argument of ioctl(), and another file handle will be sent back in gpiohandle_request::fd, if the operation successes. This new fd should be used in ioctl of GPIO_GET_LINE_VALUES_IOCTL or GPIO_SET_LINE_VALUES_IOCTL.
So the code should be
ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (ret == -1) {
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno));
}
else {
if (close(fd) == -1) {
fprintf(stderr, "Failed to close GPIO char dev.\n");
}
fd = req.fd;
}

Related

Reading and printing last N characters

I have a program that I want to use to read a file and output its last N characters (could be 50 or whatever that I have coded). From my piece of code, I get output that is question marks in diamond boxes,(unsupported unicode?)
I'm using lseek to set the cursor, could someone please assist me?
int main(int argc,char *argv[]){
int fd; //file descriptor to hold open info
int count=0; //to hold value of last 200th char number
char ch; //holds read char
char* outputString = "The file does not exist!\n";
if(!access("myFile.txt",F_OK)==0){
write(2,outputString,strlen(outputString));
exit(1);
}
fd = open("myFile.txt",O_RDONLY| O_NONBLOCK);
int ret = lseek(fd,200,SEEK_END); //get position of the last 200th item
while (ret!=0) {
write(1, &ch,1);
ret--;
}
close(fd);
return(0);
}
I don't want to use <stdio.h> functions so I'm using the file descriptors not making a FILE* object.
I slightly modified your attempt. The lseek(fd, 200, SEEK_END) seeks the file 200 characters past the end of file. If you want to read last 200 character from a file, you need to seek to 200 character to end of file, ie lseek(fd, -200, SEEK_END).
I places some comments in code to help explaining.
// please include headers when posting questions on stackoverflow
// It makes it way easier to reproduce and play with the code from others
#include <unistd.h>
#include <error.h>
// I use glibc error(3) to handle errors
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
int main(int argc,char *argv[]){
// no idea if a typo, myFile.txt != logfile.txt
if(!access("myFile.txt", F_OK) == 0) {
error(1, errno, "The file does not exist!");
exit(1);
}
int fd = open("logfile.txt", O_RDONLY | O_NONBLOCK);
if (fd == -1) {
error(1, errno, "Failed opening the file");
}
// move cursor position to the 200th characters from the end
int ret = lseek(fd, -200, SEEK_END);
if (ret == -1) {
error(1, errno, "Failed seeking the file");
}
// we break below
while (1) {
char ch = 0; // holds read char
ssize_t readed = read(fd, &ch, sizeof(ch));
if (readed == 0) {
// end-of-file, break
break;
} else if (readed == -1) {
// error handle
// actually we could handle `readed != 1`
error(1, errno, "Error reading from file");
}
// output the readed character on stdout
// note that `STDOUT_FILENO` as more readable alternative to plain `1`
write(STDOUT_FILENO, &ch, sizeof(ch));
}
close(fd);
return 0;
}

GetThreadSelectorEntry throwing ERROR_NOT_SUPPORTED for x64 App

I trying to write a very simple app to debug a Win32 64-bit app. My end goal is to get the TIB and PEB of the remote thread, but for some reason the way I did this on 32-bit app is not working for 64-bit ones (Aside from looking at Esp vs Rsp and checking SegFs vs SegGs). The code I'm trying to use is here:
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
int main(int argc, char *argv[]){
LDT_ENTRY entry;
DWORD pid;
HANDLE hThread;
HANDLE hSnapshot;
CONTEXT context;
context.ContextFlags = CONTEXT_CONTROL;
if(argc < 2){
printf("Usage: %s PID\n", argv[0]);
exit(1);
}
pid = atoi(argv[1]);
THREADENTRY32 te32;
te32.dwSize = sizeof(te32);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
while(Thread32Next(hSnapshot, &te32)){
if(pid == te32.th32OwnerProcessID){
hThread = OpenThread(THREAD_ALL_ACCESS, 0, te32.th32ThreadID);
if(!hThread)
exit(1);
if(SuspendThread(hThread) == (DWORD) -1)
exit(1);
if(!GetThreadContext(hThread, &context))
exit(1);
printf("Rsp = 0x%x\n", context.Rsp);
if(!GetThreadSelectorEntry(hThread, context.SegGs, &entry)){
LPSTR buff = NULL;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buff, 0, NULL);
printf("Error: %s\n", buff); //ERROR_NOT_SUPPORTED 50 0x32 The request is not supported.
LocalFree(buff);
exit(1);
}
}
}
CloseHandle(hSnapshot);
return 0;
}
but it's always throwing an error at "GetThreadSelectorEntry". The error code that's thrown is ERROR_NOT_SUPPORTED: The request is not supported.
I am not able to understand why it's not supported. Does anyone know why?
[EDIT]
Okay GetThreadSelectorEntry is not available to x86_64 processes, does anyone know how I can get the TIB/PEB addresses of a remote process?

gethostbyname fails on OSX (Yosemite 10.10.4)

"gethostbyname" returns a pointer to this structure:
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses from name server */
};
When I try to use it, h_name points to a valid string: the partial name I supply is expanded to the correct fully qualified host name.
The value of h_addr_list is 4
h_name is valid
h_aliasis is a valid pointer to a null pointer
h_addrtype is 2 (AF_INET, IPV4)
h_length is 0 (should be 4, or perhaps a multiple of 4)
h_addr_list is 4, fails when dereferenced.
I'm running a 32 bit process (MS Office), the h_name pointer is a valid 32 bit pointer. WTF am I doing wrong? Does gethostbyname work for other people, or on other versions of OSX?
I was able to run this small example successfully on 10.10.4 (taken from paulschreiber.com)
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
int main(int argc, char **argv) {
if (argc < 2) {
printf("Usage: %s hostname", argv[0]);
exit(-1);
}
struct hostent *hp = gethostbyname(argv[1]);
if (hp == NULL) {
printf("gethostbyname() failed\n");
} else {
printf("%s = ", hp->h_name);
unsigned int i=0;
while ( hp -> h_addr_list[i] != NULL) {
printf( "%s ", inet_ntoa( *( struct in_addr*)( hp -> h_addr_list[i])));
i++;
}
printf("\n");
}
}
However, it did segfault on 64-bit without #include <arpa/inet.h: without that, no prototype for inet_ntoa is found, the return type is assumed to be an int (when it's actually a char *), and on 64-bit this truncates the pointer and causes a segfault.

Passing input with netcat to a simple server

I am trying to write an Ruby script to pass strings to a simple server running in a VM and I am stuck at passing the strings without creating inifinite loops in my server program.
The Content of the Server(written in C):
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PORTNO 12346
int h=0,b=0,p=0;
#define BUFFER_SIZE 512
int checksec(FILE* f){
FILE* key;
char buf[1024];
if(h&b&p){
key=fopen("easy_key","r");
fread(buf,1024,1,key);
fprintf(f,"%s",buf);
fclose(key);
return 0;
}
return 1;
}
void hekers(FILE* f){
volatile int zeroWeekend;
char buf[32];
fprintf(f,"So you want to be an 31337 Hax0r?\n");
fgets(buf,40,f);
switch(strcmp("y3$\n",buf)){
case 0:
fprintf(f,"First you must get power\n");
break;
default:
fprintf(f,"Well then go away\n");
break;
}
if(zeroWeekend==0xcafebabe){
h=1;
}
return;
}
void batmenss(FILE* f){
volatile int batsignet;
char buf[32];
fprintf(f,"So you want to be the batman?\n");
fgets(buf,40,f);
switch(strcmp("YESSSSSSS\n",buf)){
case 0:
fprintf(f,"First you must get rich\n");
break;
default:
fprintf(f,"Well then go away\n");
break;
}
if(batsignet==0x12345678){
b=1;
}
return;
}
void pokemans(FILE* f){
volatile int pikachy;
char buf[32];
fprintf(f,"So you want to be the best there ever was?\n");
fgets(buf,40,f);
switch(strcmp("catchemall\n",buf)){
case 0:
fprintf(f,"First you must get respect\n\n");
break;
default:
fprintf(f,"Well then go away\n");
break;
}
if(pikachy==0xfa75beef){
p=1;
}
return;
}
void readInput(int sock){
int msg;
char choice[4];
char buffer[BUFFER_SIZE];
FILE* fptr = fdopen(sock, "r+");
char* prompt="Do you want to be a?\n"
"1.) Pokemon Master\n"
"2.) Elite Hacker\n"
"3.) The Batman\n";
while(checksec(fptr)){
fprintf(fptr,"%s",prompt);
fgets(choice,4,fptr);
switch(choice[0]){
case '1':
pokemans(fptr);
break;
case '2':
hekers(fptr);
break;
case '3':
batmenss(fptr);
break;
default:
fprintf(fptr,"\nThat is not one of the choices\n");
fflush(fptr);
}
}
fprintf(fptr, "%s", buffer);
fflush(fptr);
fclose(fptr);
return;
}
int main(int argc, char *argv[])
{
char buffer[BUFFER_SIZE];
int sockfd, newsockfd, portno, pid;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
/*
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
perror("ERROR opening socket");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
//portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
serv_addr.sin_port = htons(PORTNO);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0){
perror("ERROR on binding");
exit(1);
}
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
perror("ERROR on accept");
pid = fork();
if (pid < 0)
perror("ERROR on fork");
if (pid == 0) {
close(sockfd);
readInput(newsockfd);
return;
}
else close(newsockfd);
waitpid(-1,NULL,WNOHANG);
} /* end of while */
close(sockfd);
return 0; /* we never get here */
}
When I connect to the server, it looks like this:
user#DESKTOP-LINUX:~/Documents/tob/ctf/exploits/binary1_workshop/easy$ nc 192.168.178.40 12346
Do you want to be a?
1.) Pokemon Master
2.) Elite Hacker
3.) The Batman
Now the Program waits for an input and another string will be printed and then the Program waits for another input and so on...
Now the real problem comes when I try to use a Ruby Script that should dictate the input that the Program should get.
I tried it with this Ruby Script (Filename: script.rb):
#!/usr/bin/env ruby
firstinput = "1"
puts select + "\r\n"
secondinput = "2"
puts secondinput + "\r\n"
And executed it with this command:
user#DESKTOP-LINUX:~/Documents/Code/binary1_workshop_exploits$ ./script.rb | nc 192.168.178.40 12346
But the output is just an infinite loop of the "main menu"...
How do I fix this problem?
P.S. I am running Ubuntu 14.04 64-Bit and the VM with the Server is running Ubuntu 14.04 32-Bit

C shell printing output infinitely without stopping at gets()

I am trying to use the SIGCHLD handler but for some reason it prints of the command I gave infinitely. If I remove the struct act it works fine.
Can anyone take a look at it, I am not able to understand what the problem is.
Thanks in advance!!
/* Simplest dead child cleanup in a SIGCHLD handler. Prevent zombie processes
but dont actually do anything with the information that a child died. */
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
typedef char *string;
/* SIGCHLD handler. */
static void sigchld_hdl (int sig)
{
/* Wait for all dead processes.
* We use a non-blocking call to be sure this signal handler will not
* block if a child was cleaned up in another part of the program. */
while (waitpid(-1, NULL, WNOHANG) > 0) {
}
}
int main (int argc, char *argv[])
{
struct sigaction act;
int i;
int nbytes = 100;
char my_string[nbytes];
string arg_list[5];
char *str;
memset (&act, 0, sizeof(act));
act.sa_handler = sigchld_hdl;
if (sigaction(SIGCHLD, &act, 0)) {
perror ("sigaction");
return 1;
}
while(1){
printf("myshell>> ");
gets(my_string);
str=strtok(my_string," \n");
arg_list[0]=str;
i =1;
while ( (str=strtok (NULL," \n")) != NULL){
arg_list[i]= str;
i++;
}
if (i==1)
arg_list[i]=NULL;
else
arg_list[i+1]=NULL;
pid_t child_pid;
child_pid=fork();
if (child_pid == (pid_t)-1){
printf("ERROR OCCURED");
exit(0);
}
if(child_pid!=0){
printf("this is the parent process id is %d\n", (int) getpid());
printf("the child's process ID is %d\n",(int)child_pid);
}
else{
printf("this is the child process, with id %d\n", (int) getpid());
execvp(arg_list[0],arg_list);
printf("this should not print - ERROR occured");
abort();
}
}
return 0;
}
I haven't run your code, and am merely hypothesizing:
SIGCHLD is arriving and interrupting fgets (I'll just pretend you didn't use gets). fgets returns before actually reading any data, my_string contains the tokenized list that it had on the previous loop, you fork again, enter fgets, which is interrupted before reading any data, and repeat indefinitely.
In other words, check the return value of fgets. If it is NULL and has set errno to EINTR, then call fgets again. (Or set act.sa_flags = SA_RESTART.)

Resources