I am trying to create a posix message queue using mq_open from <mqueue.h>.
MAX_MSG and MAX_MSG_LGTH are macros currently defined as 256 and name is never longer than MAX_MSG_LGTH.
This is the code I currently have:
mqd_t func(char* name)
{
mqd_t queueId;
char localbuffer[MAX_MSG_LGTH + 1];
localbuffer[0] = '/';
strncpy(&localbuffer[1], name, MAX_MSG_LGTH);
localbuffer[MAX_MSG_LGTH] = '\0';
struct mq_attr mqAttr = {0, MAX_MSG, MAX_MSG_LGTH, 0};
queueId = mq_open(localbuffer, O_RDWR | O_CREAT, 007, &mqAttr);
return queueId;
}
input: "task1"
output: -1
errno: 22 (EINVAL)
I have checked localbuffer and the queue name is being stored correctly ("/task1").
Your MSG_MAX value is [may be] too large.
I ran your code and I reduced MSG_MAX and [eventually] it worked.
To see the system-wide values you can use, try:
head -1000 /proc/sys/fs/mqueue/*
On my system, I got:
==> /proc/sys/fs/mqueue/msg_default <==
10
==> /proc/sys/fs/mqueue/msg_max <==
10
==> /proc/sys/fs/mqueue/msgsize_default <==
8192
==> /proc/sys/fs/mqueue/msgsize_max <==
8192
==> /proc/sys/fs/mqueue/queues_max <==
256
Note that you can [as root] write to these files to change/increase the values.
Also, MSG_MAX_LGTH has nothing to do with the max size for the filename.
The max length for the filename is always 256.
Using 007 for a permission is a little screwy. It says that other users have full access, but your user has none.
I think you want 0700 or [better] 0600. Note that the leading 0 is needed to interpret the value as octal.
Related
The code inside main.c
#include <stdio.h>
#include <unistd.h>
int main() {
int c_variable = 0; // the target
for(int x = 0; x < 100; x++) {
c_variable += 5; // increase by 5 to change the value of the int
printf("%i\n", c_variable); // print current value
sleep(8); // sleep so I have time to scan memory
}
return 0;
}
What I am trying to achieve is to read the integer c_variable and then to modify it inside another .c program. I am on linux so I did ps -A | grep main and got the PID of the running program. I then did sudo scanmem PID and entered the current value of c_variable a few times. I was left with three memory addresses and executing the command set 500 changed the value the program printed, effectively changing the memory address' value to 500 instead of 35 or whatever the program was currently at. I then executed the following code
#include <stdio.h>
int main() {
const long unsigned addr = 0x772d85fa1008; // one of the three addresses from scanmem
printf("%lu\n", addr);
return 0;
}
but I got some random long string of numbers, not the current number. The tutorials and answers I have read on how to read and write memory on linux does not have to use long unsigned but can use char* or just int* instead. My memory address seems to be a bit long, I have not see memory addresses that long before. Anyhow, how do I read and write the memory address of the integer c_variable?
Edit: the output of scanmem looks something like this
info: we currently have 3 matches.
3> list
[ 0] 7771ff64b090, 6 + 1e090, stack, 20, [I64 I32 I16 I8 ]
[ 1] 7771ff64b5d8, 6 + 1e5d8, stack, 20, [I64 I32 I16 I8 ]
[ 2] 7771ff64b698, 6 + 1e698, stack, 20, [I32 I16 I8 ]
3> set 50
info: setting *0x7771ff64b090 to 0x32...
info: setting *0x7771ff64b5d8 to 0x32...
info: setting *0x7771ff64b698 to 0x32...
output
...
150
155
160
165
170
175
55
60
65
...
You're printing the actual address number, but in in decimal notation, not what is at the address.
const int *addr = (int *) 0x772d85fa1008;
printf("%d\n", *addr);
You have to declare addr as a pointer type. More specifically a pointer to an integer. Its value (0x772d85fa1008) holds the address of the integer.
Then, in the printf call you dereference it to obtain the actual integer stored at the address.
Although in practice I can't vouch for whether this is going to work, since memory in modern operating systems isn't as simple as you make it out to be. But I don't have enough knowledge to assess that.
Processes running under Linux generally have their own virtualized memory space. If you want to access memory space of another process, arrangements have been made in the Linux API, see shmctl, shmget, shmat, shmdt.
Hello I have file with text:
14
5 4
45 854
14
4
47 5
I need to write a text to a specific line. For example to the line number 4 (Doesn't matter whether I will append the text or rewrite the whole line):
14
5 4
45 854
14 new_text
4
47 5
I have found function fseek(). But in the documentation is written
fseek(file pointer,offset, position);
"Offset specifies the number of positions (bytes) to be moved from the location specified bt the position."
But I do not know the number of bites. I only know the number of lines. How to do that? Thank you
You can't do that, (text) files are not line-addressable.
Also, you can't insert data in the middle of a file.
The best way is to "spool" to a new file, i.e. read the input line by line, and write that to a new file which is the output. You can then easily keep track of which line you're on, and do whatever you want.
I will assume that you are going to be doing this many times for a single file, as such you would be better indexing the position of each newline char, for example you could use a function like this:
long *LinePosFind(int FileDes)
{
long * LinePosArr = malloc(500 * sizeof(long));
char TmpChar;
long LinesRead = 0;
long CharsRead = 0;
while(1 == read(FileDes, &TmpChar, 1))
{
if (!(LinesRead % 500)
{
LinePosArr = realloc(LinePosArr, (LinesRead + 500) * sizeof(long));
}
if (TmpChar == '\n')
{
LinePosArr[LinesRead++] = CharsRead;
}
CharsRead++;
}
return LinePosArr;
}
Then you can save the index of all the newlines for repeated use.
After this you can use it like so:
long *LineIndex = LinePosFind(FileDes);
long FourthLine = LineIndex[3];
Note I have not checked this code, just written from my head so it may need fixes, also, you should add some error checking for the malloc and read and realloc if you are using the code in production.
Here's a small C program that prints (well, supposed to print) the real and effective IDs of a process when the file has the setuid flag set. In this program, when I call getpwuid a second time (L.No 38), it tends to overwrite the value of the variable realUserName that was obtained in L.No 24. I'm unable to explain this behavior. Is this the expected behavior and why? I'm trying this in a Linux box (RHEL 2.6.18-371.1.2.el5).
1 /* Filename: test.c
2 * Notes:
3 * 1] ./test owned by user cadmn (userID: 3585)
4 * 2] ./test run by user pmn (4471)
5 * 3] ./test has the setuid bit switched-on.
6 */
7 #include <stdio.h>
8 #include <pwd.h>
9 #include <sys/types.h>
10 #include <unistd.h>
11 int main()
12 {
13
14 uid_t realId, effectiveId;
15 struct passwd *realUser, *effUser;
16
17 realId = getuid(); // realId = 4471
18 effectiveId = geteuid(); //effectiveId = 3585
19
20 printf("Real ID is %i and Effective ID is %i\n", (int)realId, (int)effectiveId);
21 //prints 4472 and 3585, respectively
22
23 realUser = getpwuid(realId);
24 char *realUserName = realUser->pw_name; //realUserName = pmn
25
26 printf("Real ID (name) at this point is %s\n", realUserName);
27 // prints pmn.
28
29 /*
30 *********************************************************
31 * *
32 * everything works as expected up to this point *
33 * *
34 *********************************************************
35 */
36
37 // The value obtained from this call is not used anywhere in this program
38 effUser = getpwuid(effectiveId);
39 printf("\nCalled getpwuid with the effectiveId\n\n");
40
41 printf("Real ID is %i and Effective ID is %i\n", (int)realId, (int)effectiveId);
42 //prints 4472 and 3585, respectively
43
44 printf("Real ID (name) at this point is %s.\n", realUserName);
45 // Expect to still see 'pmn' printed; though see 'cadmn' as the output!
46 // Why does this happen?
47
48 return 0;
49 }
50
Output:
pmn#rhel /tmp/temp > id pmn
uid=4471(pmn) gid=1000(nusers) groups=1000(nusers)
pmn#rhel /tmp/temp >
pmn#rhel /tmp/temp > id cadmn
uid=3585(cadmn) gid=401(cusers) groups=401(cusers)
pmn#rhel /tmp/temp >
pmn#rhel /tmp/temp > ls -l ./test
-r-sr-xr-x 1 cadmn cusers 9377 Dec 24 19:48 ./test
pmn#rhel /tmp/temp >
pmn#rhel /tmp/temp > ./test
Real ID is 4471 and Effective ID is 3585
Real ID (name) at this point is pmn
Called getpwuid with the effectiveId
Real ID is 4471 and Effective ID is 3585
Real ID (name) at this point is cadmn.
pmn#rhel /tmp/temp >
The behaviour you observe is the expected one.
The structure referenced by the return value of getpwuid() is defined statically internal to the latter, so it is expected to be filled (and with this overwritten) for each call to getpwuid().
This line
char * realUserName = realUser->pw_name;
just stores a reference to a value held by this statically internal structure. This value is also overwritten if the statically internal structure is overwritten by the next call to getpwuid().
To get around this there are two possibilities:
Use te reentrant version of getpwuid() which is getpwuid_r(). To be able to use it, add
#define _POSIX_SOURCE
before the very 1st #include statement in your program's sources.
Create copy of the members you need, pw_namein this case. The can be achieved by for example doing:
char * realUserName = strdup(realUser->pw_name);
Be awre that realUserName is now pointing to dynamically allocated memory, which needs to be free()ed by the program itself if not need anymore. To do so call
free(realUserName);
I've been working on writing a BitTorrent client in C in my spare time. However -- seemingly at random -- my client will fail to verify that a received piece of a torrent is correct with the message:
Failed to verify piece: #4
Background: a .torrent file contains the relevant metadata for the file-to-be-downloaded, including a SHA1 hash of each piece (a block of the file-to-be-downloaded), so -- after downloading a piece -- I take its SHA1 hash and compare it to the one provided by the torrent's metadata file.
Here's the code that handles verification:
int verify_piece (void* addr, uint64_t piece_length, unsigned char* piece_sha)
{
SHA_CTX sha;
unsigned char sha1result[20];
SHA1_Init(&sha);
SHA1_Update(&sha, addr, piece_length);
SHA1_Final(sha1result, &sha);
if (memcmp(sha1result, piece_sha, 20)) {
printf("Expected: ");
print_sha1(piece_sha);
printf("Received: ");
print_sha1(sha1result);
return 0;
} else
return 1;
}
In an attempt to track down the bug, I rigged up two functions: write_incorrect_piece() and write_correct_piece(). The first function, write_incorrect_piece() is called when verify_piece() fails. It writes the piece that failed verification to a file so that I can inspect it with hexdump.
void write_incorrect_piece (void* piece, uint32_t piece_length, uint32_t index)
{
FILE* failed_piece = fopen("failed_piece.out", "w+");
write(fileno(failed_piece), piece, piece_length);
fclose(failed_piece);
printf("ERROR: Wrote piece #%d to failed_piece.out for inspection with hexdump.\n",
index);
write_correct_piece(piece_length, index);
exit(1);
}
As you can see, write_incorrect_piece() takes the parameters void* piece, which is a pointer to the piece which failed verification, uint32_t piece_length, which is the length of the piece, and uint32_t index which is the index of the piece which failed verification. It then copies the incorrect piece to a file called failed_piece.out.
You'll notice that before calling exit(), write_incorrect_piece() calls the function write_correct_piece(). This is the second function I wrote to help with debugging this error. It takes a known good version of the file that the torrent client is attempting to download (known_good.iso) and then copies the relevant piece to a file (correct_piece.out) so that I can compare it to the file containing the incorrect piece.
void write_correct_piece (uint32_t piece_length, uint32_t index)
{
FILE* known_good = fopen("known_good.iso", "r+");
FILE* correct_piece = fopen("correct_piece.out", "w+");
/* get file size for MMAPing */
struct stat st;
stat("known_good.iso", &st);
long size = st.st_size;
void* addr = mmap(0,
size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fileno(known_good),
0);
write(fileno(correct_piece), addr + piece_length * index, piece_length);
munmap(addr, size);
fclose(known_good);
fclose(correct_piece);
}
I then took the two written files and formatted them with hexdump so that the output would be human readable and then tried to compare them via diff, like so
$ hexdump failed_piece.out > failed_piece.dump
$ hexdump correct_piece.out > correct_piece.dump
$ diff correct_piece.dump failed_piece.dump
To my surprise, diff didn't output anything. The files are exactly the same. Why, then, was the SHA1 hash of the piece different from the one expected by the torrent file? Perhaps, I then thought, the SHA1 hash from the metadata file was incorrect. If that's the case, I would expect the client to always fail to verify piece #4, so I modified the torrent client's scheduler to only attempt to download piece #4 to see if it does, in fact, always fail verification.
Successfully downloaded piece: #4
Wtf? Now I'm at an impasse. I figure a couple of different things could be causing this:
There actually is a bug in the client's network code, but I have introduced a bug in write_incorrect_piece() and write_correct_piece() so that it produces two identical files regardless of the integrity of the inputs.
There is a bug in verify_piece(), causing it to fail sporadically.
I have failed to consider something.
For the life of me, however, I can't find any problems with any of the above code, so I'm hoping you fine folks can point out what I'm missing.
The entire source of the client is at https://github.com/robertseaton/slug.
Edit: Replaced strncmp() with memcmp() in verify_piece() and cleaned up both write_incorrect_piece() and write_correct_piece().
Edit: Here's an example of the SHA1 hashes on a failed piece that seems correct when I manually diff it. As you can see, the hashes are not similar at all:
Expected: 239 66 216 164 16 120 73 24 1 236 116 173 144 85 243 152 160 165 64 231
Received: 214 94 49 185 54 159 255 201 214 137 102 23 223 76 102 138 89 94 154 69
Failed to verify piece: #13
Okay, so if we have a look at the invocation of verify_piece(), we see this:
if (verify_piece(p->torrent->mmap + index * p->torrent->piece_length,
p->torrent->piece_length, p->torrent->pieces[index].sha1)) {
Now, trivially, we know that the first and second parameters are correct since it is later reused when the program calls write_incorrect_piece() and we have already verified that its output is correct. So, we are free to focus on the third parameter, p->torrent->pieces[index].sha1.
At first glance, the parameter looks correct, since we are using index throughout the function. However, consider, what if index -- while perfectly valid on a correctly sorted array -- is being used as an index to an array that no longer contains the pieces in the assumed order?
Viola! Here's the culprit (in __schedule()):
qsort(t->pieces, t->num_pieces, sizeof(struct Piece), rarest);
Comment out the call to qsort() and the client runs as expected.
I've got a function control() which is threaded. It calls another function which parses some server responses. Here is some verbose initialization which doesn't take care of my problem.
int oct1 = 0;
int oct2 = 0;
int oct3 = 0;
int oct4 = 0;
int p1 = 0;
int p2 = 0;
sscanf(passive_ip, "%i,%i,%i,%i,%i,%i", &oct1, &oct2, &oct3, &oct4, &p1, &p2);
I often find my results messed up. For example:
S->C: 227 Entering Passive Mode (128,111,40,221,206,170)
The Parsed Result: 128.111.40.221 206,170
S->C: 227 Entering Passive Mode (128,111,40,221,80,8)
The Parsed Result: 128.111.40.221 80,8170
S->C: 227 Entering Passive Mode (128,111,40,221,241,196)
The Parsed Result: 128.111.40.221 241,196
S->C: 227 Entering Passive Mode (128,111,40,221,70,216)
The Parsed Result: 128.111.40.221 70,2166
Notice how old values are appended / jumbled with new values. Any clue as to why this might happen?
It looks like you are somehow forgetting to terminate passive_ip. Whatever you're doing should be sure to end it with a terminating null byte.