kstrtoint in sysfs for c kernel module - c

Hi I am trying to use a kobject to write to a int array from sysfs. So the input is a char* and a size variable. I cant seem to get this to work however. My expected input is "num1 num2 num3 "
static ssize_t pids_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) {
int num_count = 0;
int i = 0;
int result = 0;
int cur_pid = 0;
char *dst;
char *ddst;
printk(KERN_INFO "GPIO_DEGUG: enter");
dst = buf;
ddst = buf;
printk(KERN_INFO "GPIO_DEGUG: size of buffer %d ",count);
while(ddst < (buf + sizeof(size_t)*count)) {
ddst ++;
if (ddst[0] == ' ') {
result = kstrtoint(dst,10,&cur_pid);
dst=ddst+1;
printk(KERN_INFO "GPIO_DEGUG: kstrtoint suceeded %d ",cur_pid);
printk(KERN_INFO "GPIO_DEGUG: kstrtoint suceeded res: %d ",result);
pids[num_count] = cur_pid;
num_count += 1;
}
}
for(i=0;i<num_count;i++) {
printk(KERN_INFO "GPIO_TEST: pid: %d \n", pids[i]);
}
printk(KERN_INFO "GPIO_DEBUG: leaving\n");
return count;
}
When I echo "100 " > /sys/vt/vt7/pids I get
[ 2765.712770] GPIO_DEGUG: enter
[ 2765.724468] GPIO_DEGUG: size of buffer 5
[ 2765.735101] GPIO_DEGUG: kstrtoint suceeded 0
[ 2765.746526] GPIO_DEGUG: kstrtoint suceeded res: -22
[ 2765.757746] GPIO_DEBUG: leaving
I suppose this is an argument error any help would be nice, thanks.

Function kstrtoint expects full string to contain single integer value. The only exception is a newline character at the end of the string:
The string must be null-terminated, and may also include a single newline before its terminating null.
As you can see, string "100 " doesn't fit for that requirement: it contains exceeded space.
For parse only part of the string as an integer, you may use simple_strtol:
long val = simple_strtol(dst, &ddst, 10);
if(ddst == ddst) {/* Parsing has been failed. */};
While this function is marked as an obsolete, there is still some code in the kernel which uses it.
Another possibility is to use sscanf. It expects fixed number of integers in the string, but it is an usual situation with attributes: having complex representation of the attributes is not recommended:
The conventions for sysfs state that each attribute should contain a single, human-readable value; if you have a lot of information to return, you may want to consider splitting it into multiple attributes.
(Linux Device Drivers 3, chapter 14).

The kstrtoint function is defined here:
http://lxr.free-electrons.com/source/lib/kstrtox.c#L245
If you notice the last value of *res defined in the function is the value you wish to use. In your case cur_pid should be the value in which you want to print, the result should always be zero if it was successful. I would suggest checking result to make sure that the conversion has succeeded.
This should work:
int cur_pid, result;
char *dst = NULL;
cur_pid = result = 0;
dst = buf;
result = kstrtoint(dst, 10, &cur_pid);
if (result)
printk(KERN_INFO "GPIO_DEGUG: kstrtoint suceeded res: %d ", cur_pid);
else
printk(KERN_INFO "ERROR");

Related

C - Char array SEEMS to copy, but only within loop scope

Right now, I'm attempting to familiarize myself with C by writing a function which, given a string, will replace all instances of a target substring with a new substring. However, I've run into a problem with a reallocation of a char* array. To my eyes, it seems as though I'm able to successfully reallocate the array string to a desired new size at the end of the main loop, then perform a strcpy to fill it with an updated string. However, it fails for the following scenario:
Original input for string: "use the restroom. Then I need"
Target to replace: "the" (case insensitive)
Desired replacement value: "th'"
At the end of the loop, the line printf("result: %s\n ",string); prints out the correct phrase "use th' restroom. Then I need". However, string seems to then reset itself: the call to strcasestr in the while() statement is successful, the line at the beginning of the loop printf("string: %s \n",string); prints the original input string, and the loop continues indefinitely.
Any ideas would be much appreciated (and I apologize in advance for my flailing debug printf statements). Thanks!
The code for the function is as follows:
int replaceSubstring(char *string, int strLen, char*oldSubstring,
int oldSublen, char*newSubstring, int newSublen )
{
printf("Starting replace\n");
char* strLoc;
while((strLoc = strcasestr(string, oldSubstring)) != NULL )
{
printf("string: %s \n",string);
printf("%d",newSublen);
char *newBuf = (char *) malloc((size_t)(strLen +
(newSublen - oldSublen)));
printf("got newbuf\n");
int stringIndex = 0;
int newBufIndex = 0;
char c;
while(true)
{
if(stringIndex > 500)
break;
if(&string[stringIndex] == strLoc)
{
int j;
for(j=0; j < newSublen; j++)
{
printf("new index: %d %c --> %c\n",
j+newBufIndex, newBuf[newBufIndex+j], newSubstring[j]);
newBuf[newBufIndex+j] = newSubstring[j];
}
stringIndex += oldSublen;
newBufIndex += newSublen;
}
else
{
printf("old index: %d %c --> %c\n", stringIndex,
newBuf[newBufIndex], string[stringIndex]);
newBuf[newBufIndex] = string[stringIndex];
if(string[stringIndex] == '\0')
break;
newBufIndex++;
stringIndex++;
}
}
int length = (size_t)(strLen + (newSublen - oldSublen));
string = (char*)realloc(string,
(size_t)(strLen + (newSublen - oldSublen)));
strcpy(string, newBuf);
printf("result: %s\n ",string);
free(newBuf);
}
printf("end result: %s ",string);
}
At first the task should be clarified regarding desired behavior and interface.
The topic "Char array..." is not clear.
You provide strLen, oldSublen newSublen, so it looks that you indeed want to work just with bulk memory buffers with given length.
However, you use strcasestr, strcpy and string[stringIndex] == '\0' and also mention printf("result: %s\n ",string);.
So I assume that you want to work with "null terminated strings" that can be passed by the caller as string literals: "abc".
It is not needed to pass all those lengths to the function.
It looks that you are trying to implement recursive string replacement. After each replacement you start from the beginning.
Let's consider more complicated sets of parameters, for example, replace aba by ab in abaaba.
Case 1: single pass through input stream
Each of both old substrings can be replaced: "abaaba" => "abab"
That is how the standard sed string replacement works:
> echo "abaaba" | sed 's/aba/ab/g'
abab
Case 2: recursive replacement taking into account possible overlapping
The first replacement: "abaaba" => "ababa"
The second replacement in already replaced result: "ababa" => "abba"
Note that this case is not safe, for example replace "loop" by "loop loop". It is an infinite loop.
Suppose we want to implement a function that takes null terminated strings and the replacement is done in one pass as with sed.
In general the replacement cannot be done in place of input string (in the same memory).
Note that realloc may allocate new memory block with new address, so you should return that address to the caller.
For implementation simplicity it is possible to calculate required space for result before memory allocation (Case 1 implementation). So reallocation is not needed:
#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char* replaceSubstring(const char* string, const char* oldSubstring,
const char* newSubstring)
{
size_t strLen = strlen(string);
size_t oldSublen = strlen(oldSubstring);
size_t newSublen = strlen(newSubstring);
const char* strLoc = string;
size_t replacements = 0;
/* count number of replacements */
while ((strLoc = strcasestr(strLoc, oldSubstring)))
{
strLoc += oldSublen;
++replacements;
}
/* result size: initial size + replacement diff + sizeof('\0') */
size_t result_size = strLen + (newSublen - oldSublen) * replacements + 1;
char* result = malloc(result_size);
if (!result)
return NULL;
char* resCurrent = result;
const char* strCurrent = string;
strLoc = string;
while ((strLoc = strcasestr(strLoc, oldSubstring)))
{
memcpy(resCurrent, strCurrent, strLoc - strCurrent);
resCurrent += strLoc - strCurrent;
memcpy(resCurrent, newSubstring, newSublen);
resCurrent += newSublen;
strLoc += oldSublen;
strCurrent = strLoc;
}
strcpy(resCurrent, strCurrent);
return result;
}
int main()
{
char* res;
res = replaceSubstring("use the restroom. Then I need", "the", "th");
printf("%s\n", res);
free(res);
res = replaceSubstring("abaaba", "aba", "ab");
printf("%s\n", res);
free(res);
return 0;
}

String character dropping off?

I have been using strcat to join several strings. Everything appears to be correct, prints:
/proc/573/fd/ <- with the backslash
13 <- length
After I try to copy the "src" string with strcpy to another string, the trailing character doesn't print in either the "dest" or the "src" strings:
/proc/573/fd <- same string prints without the backslash?
13 <- length is unchanged?
If I call strlen the length shows it is unchanged though?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// This function counts the number of digit places in 'pid'
int pid_digit_places(int pid)
{
int n = pid;
int places = 0;
while (n)
n /= 10;
places++;
return places;
}
char *construct_path(int pid, char *dir)
{
// get count of places in pid
int places = pid_digit_places(pid);
char *pid_str = calloc(places, sizeof(char));
// create string of pid
sprintf(pid_str, "%d", pid);
char *proc = "/proc/";
size_t plen = strlen(proc);
size_t dlen = strlen(dir) + 1;
char *path = calloc(plen + dlen + places, sizeof(char));
strcat(path, proc);
strcat(path, pid_str);
strcat(path, dir);
return path;
}
void fd_walk(int pid)
{
char *fd = "/fd/";
char *fdpath = construct_path(pid, fd);
// prints "/proc/573/fd/ - as expected
printf("Before: %s\n", fdpath);
// shows a length of 13
printf("Size Before: %d\n", (int)strlen(fdpath));
char *test = calloc(strlen(fdpath) + 1, sizeof(char));
strcpy(test, fdpath);
// prints "/proc/573/fd" no trailing "/"
printf("Copied Str: %s\n", test);
//shows a length of 13 though
printf("Copied Size: %d\n", (int)strlen(test));
// prints "/proc/573/fd" no trailing "/" now
printf("After: %s\n", fdpath);
// still shows length of 13
printf("Size After: %d\n", (int)strlen(fdpath));
}
int main(void)
{
// integer to create path around
int pid = 573;
fd_walk(pid);
return 0;
}
I'm compiling on gcc-4.8.2 with -Wall:
gcc -o src src.c -Wall
I've popped this small example into ideone.
I've made sure to add an extra space for the null-terminator when allocating memory.
I've thought to re-examine how I'm intializing my pointers first and haven't seen anything wrong? How is the string printing as expected with printf and then after copying it, printf prints something different -- undefined behavior?
I have executed your exact code with no troubles. Nonetheless, I see two possible problems:
// This function counts the number of digit places in 'pid'
int pid_digit_places(int pid)
{
int n = pid;
int places = 0;
while (n) { // <-- The braces were missing here.
n /= 10;
places++;
}
return places;
}
char *construct_path(int pid, char *dir)
{
// get count of places in pid
int places = pid_digit_places(pid);
// You need "places" bytes for the digits, plus one for the zero
char *pid_str = calloc(places + 1, sizeof(char));
However, in general, I wouldn't waste time to allocate exactly the memory I needed; the extra code more than compensates in size and complexity.
Just make a guess on the largest possible value, and enforce that guess:
// avoid pid_digit_places altogether
pid_str = malloc(16);
if (pid > 999999999999L) {
// fprintf an error and abort.
// Better yet, see whether this is a limit #define'd in the OS,
// and place an appropriate compile-time # warning. Chances are
// that unless your code's trivial, running it on a system with
// such large PIDs (and therefore likely so different an arch!)
// would cause some other troube to pop up.
// With an # error in place, you save also the pid check!
}

C - Problems extracting data from buffer. Possibly endianess-related

I'm having some difficulties extracting data from a buffer using memcpy.
First, I memcpy some variables into a buffer:
int l1_connect(const char* hostname, int port) {
// Variables to be stored in the buffer
char *msg = "Hi, I'm a message"; // strlen(msg) == 17
uint16_t sender_id = htons(1); // sizeof(sender_id) == 2
uint16_t packet_size = htons(sizeof(packet_size)+sizeof(sender_id)+strlen(msg)); // sizeof(packet_size) == 2
// Checking values
printf("l1_connect():\nsender_id: %d, packet_size: %d\n\n", ntohs(sender_id), ntohs(packet_size));
// sender_id == 1, packet_size == 21
// The buffer
char buf[100];
// Copying everything
memcpy(&buf, &sender_id, sizeof(sender_id));
memcpy(&buf+sizeof(sender_id), &packet_size, sizeof(packet_size));
memcpy(&buf+sizeof(sender_id)+sizeof(packet_size), &msg, strlen(msg));
// Passing buf to another function
int bytes_sent = l1_send(1, buf, sizeof(buf));
}
I then try to extract that data (checking, before sending over UDP socket):
int l1_send( int device, const char* buf, int length ) {
// Variables in which to store extracted data
uint16_t id = 0;
uint16_t size = 0;
char msg[50];
memcpy(&id, &buf, sizeof(id));
memcpy(&size, &buf+sizeof(id), sizeof(size));
int remaining = ntohs(size) - (sizeof(id) + sizeof(size));
printf("l1_send():\nremaining: %d\n", remaining); // -37041
// memcpy-ing with correct(?) offset
memcpy(&msg, &buf+sizeof(id)+sizeof(size), 50);
msg[49] = '\0';
printf("id: %d\n", ntohs(id)); // 8372
printf("size: %d\n", ntohs(size)); // 37045
printf("msg: %s\n", msg); // ��$_�
return 0; // For now
}
As you can see, the values aren't quite what I'm expecting. Can anyone tell me what I'm doing wrong?
Your pointer math is incorrect. You're using &buf where you should just be using buf. If this doesn't explain what is wrong, nothing else I can say will:
#include <stdio.h>
int main(int argc, char **argv)
{
char buff[100];
printf("buff : %p\nbuff+10 : %p\n&buff+10 : %p\n", buff, buff+10, &buff+10);
return 0;
}
Output (varies by platform, obviously)
buff : 0xbf87a8bc
buff+10 : 0xbf87a8c6
&buff+10 : 0xbf87aca4
See it live. The math you're doing is incrementing by type, which for &buf is a pointer to array of 100 chars; not a simple char address. Therefore, &buff + 10 (in my sample) says "give me the 10th array of 100 chars from where I am now.". The subsequent write is invoking undefined behavior as a consequence.
Valgrind is your buddy here, btw. It would have caught this in a heartbeat.
Update
May as well fill in the entire gambit while I'm here. This is also wrong in l1_send:
memcpy(&id, &buf, sizeof(id));
// this------^
and the subsequent other areas you're using it in that function. You're taking the address of a parameter pointer, not the value within it. I'm confident you need buf there as well.
Try this:
memcpy(buf, &sender_id, sizeof(sender_id));
memcpy(buf + sizeof(sender_id), &packet_size, sizeof(packet_size));
memcpy(buf + sizeof(sender_id) + sizeof(packet_size), msg, strlen(msg));
To help you understand what is wrong with your code, you can read this.
Related: Pointer math vs. Array index

sprintf and allocating memory

I have a structure where I stored some values as shown below:
struct cmd {
char *pname;
char *pdesc;
};
Following initialization I made as:
struct cmd[] = {{"show", "show items"},
{"exit", "exit the shell"},
{"setitem", "setting item"}
};
I'm using sprinf() to print by storing all the pname ans pdesc as below,
int length = 0;
char *resultcmd;
for (indx = 0; indx< cmdCount; indx++) {
length += sprintf(resultcmd+length, cmd[indx].pname, cmd[indx].pdesc);
}
Please help me how to allocate memory for resultcmd, It worked when i make resulecmd as array of some length, but if more pname and pdesc are added buffer overruns. Please help me.
If you want safely output data to buffer resultcmd you have to find out its length before and use it:
size_t length = 1; // 1 symbol needed to store \0',
// because strlen() returns length
// without NULL-termination symbol
// compute length:
for (intx = 0; indx < cmdCount; indx++) {
length += strlen(cmd[indx].pname) + strlen(cmd[indx].pdesc);
}
char *resultcmd = malloc(length);
int written = 0, ret = 0;
// print cmds to C string
for (indx = 0; indx < cmdCount; indx++) {
ret = snprintf (resultcmd + written, length - written,
"%s%s", cmd[indx].pname, cmd[indx].pdesc))
if (0 > ret) {
fprintf (stderr, "snprintf() error: %s\n", strerror(errno));
break;
} else {
written += ret;
}
}
/*
* some useful code here
*/
free(resultcmd);
You can use snprintf(char *dest, size_t maxlen, char *fmt, ...) to bound the size of your print. If the function fails, it returns the number of characters that would have been written, had there been enough space; so that +1 is what you need to realloc.

Print unsigned int (base 10 / decimal) value of MPI

I'm trying to confirm/get the unsigned int (base 10 / decimal) value of an hex'd mpi value. I'm using the following code:
#include <gcrypt.h>
#include <stdio.h>
static gcry_mpi_t privkey = NULL;
int main(){
char *parmstr = "48BFDA215C31A9F0B226B3DB11F862450A0F30DA";
printf("starting program\n");
gcry_mpi_scan(&privkey, GCRYMPI_FMT_HEX, (char *)parmstr, 0, NULL);
printf("printing hashed (?) mpi\n");
gcry_mpi_dump(privkey);
printf("\n");
size_t gablen;
unsigned char *result;
/* get length */
gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &gablen, privkey);
result = gcry_malloc_secure(gablen);
/* get actual value */
gcry_mpi_print (GCRYMPI_FMT_USG, result, gablen, NULL, privkey);
/* print actual value */
printf("result: %s\n", result);
printf("finished\n");
}
and i'm getting the following result:
$ ./foo
starting program
printing hashed (?) mpi
48BFDA215C31A9F0B226B3DB11F862450A0F30DA
result: H¿Ú!\1©ð²&³ÛøbE
0Ú
finished
I would the 'result: ' line to print the actual unsigned int (base 10 / decimal) value.
The private key is taking from the Off-The-Record Pidgin plug-in that i'm trying to work with.
EDIT:
can anybody confirm that the actual unsigned int (base 10 / decimal) value should be
415325779662433871844955547383752003988573073626
I could probably update the program to create a new mpi in gcrypt with this value and see if the HEX value is the same as what i already have. I will do this later today.
EDIT 2:
So i'm trying to do the following to print the HEX value of the int value mentioned above. Something is going wrong:
gcry_mpi_t cript_prime;
char buffer[50] = {0};
char number[50] = {0};
cript_prime = gcry_mpi_new(50);
strcpy(number,"415325779662433871844955547383752003988573073626");
gcry_mpi_scan(&cript_prime,GCRYMPI_FMT_USG,number,sizeof(number),NULL);
gcry_mpi_print(GCRYMPI_FMT_USG,buffer,sizeof(buffer),NULL,cript_prime);
printf("The number tested is: %s\n",buffer);
printf("trying to convert to HEX\n");
/* get actual value */
gcry_mpi_print (GCRYMPI_FMT_HEX, buffer, sizeof(buffer), NULL, cript_prime);
/* print actual value */
printf("result: %s\n", buffer);
The output is:
result: 48BFDA215C31A9F0B226B3DB11F862450A0F30DA
The number tested is: 415325779662433871844955547383752003988573073626
trying to convert to HEX
result: 415325779662433871844955547383752003988573073626
EDIT 3:
I updated the post a bit, basically i'm trying to print the base10 decimal value of an hex value that is generated by the gcrypt library. I'm looking for this value to confirm an implementation that i made to read these values. I was looking for a gcrypt function to achieve this. It seems that gcrypt doesn't supports this?
result[1] = (gablen >> 24) & 0xff;
This line puts a nul byte into the byte at offset 1 into result. I don't see where you ever initialize the byte at offset zero, but the bytes at offsets 2 and later are past the end of the string you've constructed. The string it's formatting starts at result+5, so that's what you should print here:
gcry_mpi_print (GCRYMPI_FMT_USG, result + 5, gablen, NULL, privkey);
...
printf("result: %s\n", result + 5);
Here is a working script, the buffer was too small
#include <gcrypt.h>
#include <stdio.h>
int main(){
gcry_error_t err;
gcry_mpi_t cript_prime;
unsigned char buffer[401] = {0};
char number[101] = {0};
cript_prime = gcry_mpi_new(101);
strcpy(number, "415325779662433871844955547383752003988573073626");
gcry_mpi_scan(&cript_prime, GCRYMPI_FMT_USG, number, sizeof(number), NULL);
err = gcry_mpi_print(GCRYMPI_FMT_USG, buffer, sizeof(buffer), NULL, cript_prime);
if (err != 0){
printf("error: %d\n", err);
return -1;
}
printf("The number tested is: %s\n",buffer);
printf("trying to convert to HEX\n");
/* get actual value */
err = gcry_mpi_print(GCRYMPI_FMT_HEX, buffer, sizeof(buffer), NULL, cript_prime);
if (err != 0){
gcry_err_code_t code = gcry_err_code(err);
printf("error: %d\n", code);
return -1;
}
/* print actual value */
printf("result: %s\n", buffer);
printf("finished\n");
return 0;
}
I also confirmed my thoughts using this website: http://www.unitconversion.org/numbers/base-10-to-base-16-conversion.html
This will show that hex (base-16) 48BFDA215C31A9F0B226B3DB11F862450A0F30DA actual is 415325779662433762080404206464628666084640806848 (base-10)

Resources