When do Linux system calls trigger a segfault vs returning EFAULT?
I'm trying to understand when clock_gettime()
can lead to errors. The man page lists the following two possibilities:
- EFAULT tp points outside the accessible address space.
- EINVAL The clk_id specified is not supported on this system.
It's easy to trigger an EINVAL
error but I'm not able to get clock_gettime()
to set errno
to EFAULT
. Instead, the kernel sends a SIGSEGV signal to terminate the program. For instance, in the following code:
#include <time.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int main()
{
struct timespec tp;
double time;
if (clock_gettime(CLOCK_MONOTONIC, &tp + 4096) == -1) {
if (errno == EINVAL) {
perror("EINVAL");
return EXIT_FAILURE;
} else if (errno == EFAULT) {
perror("EFAULT");
return EXIT_FAILURE;
} else {
perror("something else");
return EXIT_FAILURE;
}
}
time = tp.tv_sec + 1e-9 * tp.tv_nsec;
printf("%fn", time);
}
How does the Linux kernel choose between triggering a segmentation fault and having the system call return -EINVAL
? When will it choose to do the latter? If the kernel always sends the signal, is it actually necessary to check whether errno
equals EFAULT
?
I'm running Linux kernel 4.15 and I compiled the program with (using clang v6.0):
clang -g -O0 -Wall -Wextra -Wshadow -Wstrict-aliasing -ansi -pedantic -Werror -std=gnu11 file.c -o file
c linux error-handling
add a comment |
I'm trying to understand when clock_gettime()
can lead to errors. The man page lists the following two possibilities:
- EFAULT tp points outside the accessible address space.
- EINVAL The clk_id specified is not supported on this system.
It's easy to trigger an EINVAL
error but I'm not able to get clock_gettime()
to set errno
to EFAULT
. Instead, the kernel sends a SIGSEGV signal to terminate the program. For instance, in the following code:
#include <time.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int main()
{
struct timespec tp;
double time;
if (clock_gettime(CLOCK_MONOTONIC, &tp + 4096) == -1) {
if (errno == EINVAL) {
perror("EINVAL");
return EXIT_FAILURE;
} else if (errno == EFAULT) {
perror("EFAULT");
return EXIT_FAILURE;
} else {
perror("something else");
return EXIT_FAILURE;
}
}
time = tp.tv_sec + 1e-9 * tp.tv_nsec;
printf("%fn", time);
}
How does the Linux kernel choose between triggering a segmentation fault and having the system call return -EINVAL
? When will it choose to do the latter? If the kernel always sends the signal, is it actually necessary to check whether errno
equals EFAULT
?
I'm running Linux kernel 4.15 and I compiled the program with (using clang v6.0):
clang -g -O0 -Wall -Wextra -Wshadow -Wstrict-aliasing -ansi -pedantic -Werror -std=gnu11 file.c -o file
c linux error-handling
I don't believe that a system call can ever segfault. However, glibc can segfault, and a lot of functions that you think are system calls are actually glibc functions.
– immibis
Nov 19 '18 at 23:20
add a comment |
I'm trying to understand when clock_gettime()
can lead to errors. The man page lists the following two possibilities:
- EFAULT tp points outside the accessible address space.
- EINVAL The clk_id specified is not supported on this system.
It's easy to trigger an EINVAL
error but I'm not able to get clock_gettime()
to set errno
to EFAULT
. Instead, the kernel sends a SIGSEGV signal to terminate the program. For instance, in the following code:
#include <time.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int main()
{
struct timespec tp;
double time;
if (clock_gettime(CLOCK_MONOTONIC, &tp + 4096) == -1) {
if (errno == EINVAL) {
perror("EINVAL");
return EXIT_FAILURE;
} else if (errno == EFAULT) {
perror("EFAULT");
return EXIT_FAILURE;
} else {
perror("something else");
return EXIT_FAILURE;
}
}
time = tp.tv_sec + 1e-9 * tp.tv_nsec;
printf("%fn", time);
}
How does the Linux kernel choose between triggering a segmentation fault and having the system call return -EINVAL
? When will it choose to do the latter? If the kernel always sends the signal, is it actually necessary to check whether errno
equals EFAULT
?
I'm running Linux kernel 4.15 and I compiled the program with (using clang v6.0):
clang -g -O0 -Wall -Wextra -Wshadow -Wstrict-aliasing -ansi -pedantic -Werror -std=gnu11 file.c -o file
c linux error-handling
I'm trying to understand when clock_gettime()
can lead to errors. The man page lists the following two possibilities:
- EFAULT tp points outside the accessible address space.
- EINVAL The clk_id specified is not supported on this system.
It's easy to trigger an EINVAL
error but I'm not able to get clock_gettime()
to set errno
to EFAULT
. Instead, the kernel sends a SIGSEGV signal to terminate the program. For instance, in the following code:
#include <time.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int main()
{
struct timespec tp;
double time;
if (clock_gettime(CLOCK_MONOTONIC, &tp + 4096) == -1) {
if (errno == EINVAL) {
perror("EINVAL");
return EXIT_FAILURE;
} else if (errno == EFAULT) {
perror("EFAULT");
return EXIT_FAILURE;
} else {
perror("something else");
return EXIT_FAILURE;
}
}
time = tp.tv_sec + 1e-9 * tp.tv_nsec;
printf("%fn", time);
}
How does the Linux kernel choose between triggering a segmentation fault and having the system call return -EINVAL
? When will it choose to do the latter? If the kernel always sends the signal, is it actually necessary to check whether errno
equals EFAULT
?
I'm running Linux kernel 4.15 and I compiled the program with (using clang v6.0):
clang -g -O0 -Wall -Wextra -Wshadow -Wstrict-aliasing -ansi -pedantic -Werror -std=gnu11 file.c -o file
c linux error-handling
c linux error-handling
edited Nov 19 '18 at 23:24
MattHusz
asked Nov 19 '18 at 23:18
MattHuszMattHusz
7516
7516
I don't believe that a system call can ever segfault. However, glibc can segfault, and a lot of functions that you think are system calls are actually glibc functions.
– immibis
Nov 19 '18 at 23:20
add a comment |
I don't believe that a system call can ever segfault. However, glibc can segfault, and a lot of functions that you think are system calls are actually glibc functions.
– immibis
Nov 19 '18 at 23:20
I don't believe that a system call can ever segfault. However, glibc can segfault, and a lot of functions that you think are system calls are actually glibc functions.
– immibis
Nov 19 '18 at 23:20
I don't believe that a system call can ever segfault. However, glibc can segfault, and a lot of functions that you think are system calls are actually glibc functions.
– immibis
Nov 19 '18 at 23:20
add a comment |
2 Answers
2
active
oldest
votes
clock_gettime
is probably not executing as a syscall, but rather in userspace as part of the vdso. If you actually perform a syscall by using the syscall
function with SYS_clock_gettime
as its argument, I would expect you to see EFAULT
.
With that said, EFAULT
is not ever something you should expect to be able to rely on. As soon as you pass an invalid pointer to a function that requires a valid pointer as part of its interface contract, you have undefined behavior, and a segfault or an error is only one possible manifestation among many. From this perspective it's something of a mistake that EFAULT
is even documented.
add a comment |
I'm trying to understand when clock_gettime() can lead to errors.
Ok.
How does the Linux kernel choose between triggering a segmentation fault and having the system call return -EINVAL? When will it choose to do the latter?
It's easy. There are some checks in case they are true the function sets errno. In case you access a protected memory region the kernel sends SIGSEGV to your process.
If you inspect the __clock_gettime from glibc function you see that:
switch (clock_id)
{
#ifdef SYSDEP_GETTIME
SYSDEP_GETTIME;
#endif
#ifndef HANDLED_REALTIME
case CLOCK_REALTIME:
...
break;
#endif
default:
#if HP_TIMING_AVAIL
if ((clock_id ...) == CLOCK_THREAD_CPUTIME_ID)
...
else
#endif
__set_errno (EINVAL);
break;
The glibc wrapper set's EINVAL in case of some strange clock_id value.
Dereferencing a pointer value outside any valid memory reagion in undefined bahaviour and spawns nasal demons. On Linux a SIGSEGV is a signal sent to a process which tries to write to a protected memory region.
The following code spawns demons and should raise SIGSEGV:
struct timespec tp;
*(&tp + 4096) = (struct timespec){0};
so does the following code:
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp + 4096)
If the kernel always sends the signal,
Not really. If it so just happens that sizeof(struct timespec)
bytes starting from &tp + 4096
will not be inside protected memory region, the kernel will not send any signal, cause it would think, you write inside you own memory.
is it actually necessary to check whether errno equals EFAULT?
It's not necessary to check for any errors. I think you mix interpreting errors with checking for them. If you machine follows the specification you mentioned, if clock_gettime
returns EFAULT you can write your program so it assumes that the underlying implementation on your machine of clock_gettime
follows the linux manual page of clock_gettime
. However, as you discovered, it does not, instead undefined bahaviour happens and the kernel raises SIGSEGV. Which only means that the underlying implementation of the clock_gettime
function does not follow the manual. The POSIX does not specify the EFAULT errno code. However I believe there may exists implementations which may return EFAULT errno or any other errno codes. However, what do you want your program to do when receiving EFAULT error? How to recover from such error? If these question bear any significance to you, then it may be reasonable to write an EFAULT handler for the clock_gettime
function.
Please note, you are using linux. Linux, kernel and glibc, mostly are licensed under the GNU General License or GNU Lesser General License, which has the following in it:
BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
The question bears down to trust: do you believe your system's clock_gettime()
to follow the linux manual implementation? I don't. If your system would be POSIX certificate, you could place some more trust in the functions that they will work as the manual says. No one guarantees you that, it is just a good will of many hardworking people that it works.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53384022%2fwhen-do-linux-system-calls-trigger-a-segfault-vs-returning-efault%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
clock_gettime
is probably not executing as a syscall, but rather in userspace as part of the vdso. If you actually perform a syscall by using the syscall
function with SYS_clock_gettime
as its argument, I would expect you to see EFAULT
.
With that said, EFAULT
is not ever something you should expect to be able to rely on. As soon as you pass an invalid pointer to a function that requires a valid pointer as part of its interface contract, you have undefined behavior, and a segfault or an error is only one possible manifestation among many. From this perspective it's something of a mistake that EFAULT
is even documented.
add a comment |
clock_gettime
is probably not executing as a syscall, but rather in userspace as part of the vdso. If you actually perform a syscall by using the syscall
function with SYS_clock_gettime
as its argument, I would expect you to see EFAULT
.
With that said, EFAULT
is not ever something you should expect to be able to rely on. As soon as you pass an invalid pointer to a function that requires a valid pointer as part of its interface contract, you have undefined behavior, and a segfault or an error is only one possible manifestation among many. From this perspective it's something of a mistake that EFAULT
is even documented.
add a comment |
clock_gettime
is probably not executing as a syscall, but rather in userspace as part of the vdso. If you actually perform a syscall by using the syscall
function with SYS_clock_gettime
as its argument, I would expect you to see EFAULT
.
With that said, EFAULT
is not ever something you should expect to be able to rely on. As soon as you pass an invalid pointer to a function that requires a valid pointer as part of its interface contract, you have undefined behavior, and a segfault or an error is only one possible manifestation among many. From this perspective it's something of a mistake that EFAULT
is even documented.
clock_gettime
is probably not executing as a syscall, but rather in userspace as part of the vdso. If you actually perform a syscall by using the syscall
function with SYS_clock_gettime
as its argument, I would expect you to see EFAULT
.
With that said, EFAULT
is not ever something you should expect to be able to rely on. As soon as you pass an invalid pointer to a function that requires a valid pointer as part of its interface contract, you have undefined behavior, and a segfault or an error is only one possible manifestation among many. From this perspective it's something of a mistake that EFAULT
is even documented.
answered Nov 19 '18 at 23:25
R..R..
156k26260563
156k26260563
add a comment |
add a comment |
I'm trying to understand when clock_gettime() can lead to errors.
Ok.
How does the Linux kernel choose between triggering a segmentation fault and having the system call return -EINVAL? When will it choose to do the latter?
It's easy. There are some checks in case they are true the function sets errno. In case you access a protected memory region the kernel sends SIGSEGV to your process.
If you inspect the __clock_gettime from glibc function you see that:
switch (clock_id)
{
#ifdef SYSDEP_GETTIME
SYSDEP_GETTIME;
#endif
#ifndef HANDLED_REALTIME
case CLOCK_REALTIME:
...
break;
#endif
default:
#if HP_TIMING_AVAIL
if ((clock_id ...) == CLOCK_THREAD_CPUTIME_ID)
...
else
#endif
__set_errno (EINVAL);
break;
The glibc wrapper set's EINVAL in case of some strange clock_id value.
Dereferencing a pointer value outside any valid memory reagion in undefined bahaviour and spawns nasal demons. On Linux a SIGSEGV is a signal sent to a process which tries to write to a protected memory region.
The following code spawns demons and should raise SIGSEGV:
struct timespec tp;
*(&tp + 4096) = (struct timespec){0};
so does the following code:
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp + 4096)
If the kernel always sends the signal,
Not really. If it so just happens that sizeof(struct timespec)
bytes starting from &tp + 4096
will not be inside protected memory region, the kernel will not send any signal, cause it would think, you write inside you own memory.
is it actually necessary to check whether errno equals EFAULT?
It's not necessary to check for any errors. I think you mix interpreting errors with checking for them. If you machine follows the specification you mentioned, if clock_gettime
returns EFAULT you can write your program so it assumes that the underlying implementation on your machine of clock_gettime
follows the linux manual page of clock_gettime
. However, as you discovered, it does not, instead undefined bahaviour happens and the kernel raises SIGSEGV. Which only means that the underlying implementation of the clock_gettime
function does not follow the manual. The POSIX does not specify the EFAULT errno code. However I believe there may exists implementations which may return EFAULT errno or any other errno codes. However, what do you want your program to do when receiving EFAULT error? How to recover from such error? If these question bear any significance to you, then it may be reasonable to write an EFAULT handler for the clock_gettime
function.
Please note, you are using linux. Linux, kernel and glibc, mostly are licensed under the GNU General License or GNU Lesser General License, which has the following in it:
BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
The question bears down to trust: do you believe your system's clock_gettime()
to follow the linux manual implementation? I don't. If your system would be POSIX certificate, you could place some more trust in the functions that they will work as the manual says. No one guarantees you that, it is just a good will of many hardworking people that it works.
add a comment |
I'm trying to understand when clock_gettime() can lead to errors.
Ok.
How does the Linux kernel choose between triggering a segmentation fault and having the system call return -EINVAL? When will it choose to do the latter?
It's easy. There are some checks in case they are true the function sets errno. In case you access a protected memory region the kernel sends SIGSEGV to your process.
If you inspect the __clock_gettime from glibc function you see that:
switch (clock_id)
{
#ifdef SYSDEP_GETTIME
SYSDEP_GETTIME;
#endif
#ifndef HANDLED_REALTIME
case CLOCK_REALTIME:
...
break;
#endif
default:
#if HP_TIMING_AVAIL
if ((clock_id ...) == CLOCK_THREAD_CPUTIME_ID)
...
else
#endif
__set_errno (EINVAL);
break;
The glibc wrapper set's EINVAL in case of some strange clock_id value.
Dereferencing a pointer value outside any valid memory reagion in undefined bahaviour and spawns nasal demons. On Linux a SIGSEGV is a signal sent to a process which tries to write to a protected memory region.
The following code spawns demons and should raise SIGSEGV:
struct timespec tp;
*(&tp + 4096) = (struct timespec){0};
so does the following code:
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp + 4096)
If the kernel always sends the signal,
Not really. If it so just happens that sizeof(struct timespec)
bytes starting from &tp + 4096
will not be inside protected memory region, the kernel will not send any signal, cause it would think, you write inside you own memory.
is it actually necessary to check whether errno equals EFAULT?
It's not necessary to check for any errors. I think you mix interpreting errors with checking for them. If you machine follows the specification you mentioned, if clock_gettime
returns EFAULT you can write your program so it assumes that the underlying implementation on your machine of clock_gettime
follows the linux manual page of clock_gettime
. However, as you discovered, it does not, instead undefined bahaviour happens and the kernel raises SIGSEGV. Which only means that the underlying implementation of the clock_gettime
function does not follow the manual. The POSIX does not specify the EFAULT errno code. However I believe there may exists implementations which may return EFAULT errno or any other errno codes. However, what do you want your program to do when receiving EFAULT error? How to recover from such error? If these question bear any significance to you, then it may be reasonable to write an EFAULT handler for the clock_gettime
function.
Please note, you are using linux. Linux, kernel and glibc, mostly are licensed under the GNU General License or GNU Lesser General License, which has the following in it:
BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
The question bears down to trust: do you believe your system's clock_gettime()
to follow the linux manual implementation? I don't. If your system would be POSIX certificate, you could place some more trust in the functions that they will work as the manual says. No one guarantees you that, it is just a good will of many hardworking people that it works.
add a comment |
I'm trying to understand when clock_gettime() can lead to errors.
Ok.
How does the Linux kernel choose between triggering a segmentation fault and having the system call return -EINVAL? When will it choose to do the latter?
It's easy. There are some checks in case they are true the function sets errno. In case you access a protected memory region the kernel sends SIGSEGV to your process.
If you inspect the __clock_gettime from glibc function you see that:
switch (clock_id)
{
#ifdef SYSDEP_GETTIME
SYSDEP_GETTIME;
#endif
#ifndef HANDLED_REALTIME
case CLOCK_REALTIME:
...
break;
#endif
default:
#if HP_TIMING_AVAIL
if ((clock_id ...) == CLOCK_THREAD_CPUTIME_ID)
...
else
#endif
__set_errno (EINVAL);
break;
The glibc wrapper set's EINVAL in case of some strange clock_id value.
Dereferencing a pointer value outside any valid memory reagion in undefined bahaviour and spawns nasal demons. On Linux a SIGSEGV is a signal sent to a process which tries to write to a protected memory region.
The following code spawns demons and should raise SIGSEGV:
struct timespec tp;
*(&tp + 4096) = (struct timespec){0};
so does the following code:
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp + 4096)
If the kernel always sends the signal,
Not really. If it so just happens that sizeof(struct timespec)
bytes starting from &tp + 4096
will not be inside protected memory region, the kernel will not send any signal, cause it would think, you write inside you own memory.
is it actually necessary to check whether errno equals EFAULT?
It's not necessary to check for any errors. I think you mix interpreting errors with checking for them. If you machine follows the specification you mentioned, if clock_gettime
returns EFAULT you can write your program so it assumes that the underlying implementation on your machine of clock_gettime
follows the linux manual page of clock_gettime
. However, as you discovered, it does not, instead undefined bahaviour happens and the kernel raises SIGSEGV. Which only means that the underlying implementation of the clock_gettime
function does not follow the manual. The POSIX does not specify the EFAULT errno code. However I believe there may exists implementations which may return EFAULT errno or any other errno codes. However, what do you want your program to do when receiving EFAULT error? How to recover from such error? If these question bear any significance to you, then it may be reasonable to write an EFAULT handler for the clock_gettime
function.
Please note, you are using linux. Linux, kernel and glibc, mostly are licensed under the GNU General License or GNU Lesser General License, which has the following in it:
BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
The question bears down to trust: do you believe your system's clock_gettime()
to follow the linux manual implementation? I don't. If your system would be POSIX certificate, you could place some more trust in the functions that they will work as the manual says. No one guarantees you that, it is just a good will of many hardworking people that it works.
I'm trying to understand when clock_gettime() can lead to errors.
Ok.
How does the Linux kernel choose between triggering a segmentation fault and having the system call return -EINVAL? When will it choose to do the latter?
It's easy. There are some checks in case they are true the function sets errno. In case you access a protected memory region the kernel sends SIGSEGV to your process.
If you inspect the __clock_gettime from glibc function you see that:
switch (clock_id)
{
#ifdef SYSDEP_GETTIME
SYSDEP_GETTIME;
#endif
#ifndef HANDLED_REALTIME
case CLOCK_REALTIME:
...
break;
#endif
default:
#if HP_TIMING_AVAIL
if ((clock_id ...) == CLOCK_THREAD_CPUTIME_ID)
...
else
#endif
__set_errno (EINVAL);
break;
The glibc wrapper set's EINVAL in case of some strange clock_id value.
Dereferencing a pointer value outside any valid memory reagion in undefined bahaviour and spawns nasal demons. On Linux a SIGSEGV is a signal sent to a process which tries to write to a protected memory region.
The following code spawns demons and should raise SIGSEGV:
struct timespec tp;
*(&tp + 4096) = (struct timespec){0};
so does the following code:
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp + 4096)
If the kernel always sends the signal,
Not really. If it so just happens that sizeof(struct timespec)
bytes starting from &tp + 4096
will not be inside protected memory region, the kernel will not send any signal, cause it would think, you write inside you own memory.
is it actually necessary to check whether errno equals EFAULT?
It's not necessary to check for any errors. I think you mix interpreting errors with checking for them. If you machine follows the specification you mentioned, if clock_gettime
returns EFAULT you can write your program so it assumes that the underlying implementation on your machine of clock_gettime
follows the linux manual page of clock_gettime
. However, as you discovered, it does not, instead undefined bahaviour happens and the kernel raises SIGSEGV. Which only means that the underlying implementation of the clock_gettime
function does not follow the manual. The POSIX does not specify the EFAULT errno code. However I believe there may exists implementations which may return EFAULT errno or any other errno codes. However, what do you want your program to do when receiving EFAULT error? How to recover from such error? If these question bear any significance to you, then it may be reasonable to write an EFAULT handler for the clock_gettime
function.
Please note, you are using linux. Linux, kernel and glibc, mostly are licensed under the GNU General License or GNU Lesser General License, which has the following in it:
BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
The question bears down to trust: do you believe your system's clock_gettime()
to follow the linux manual implementation? I don't. If your system would be POSIX certificate, you could place some more trust in the functions that they will work as the manual says. No one guarantees you that, it is just a good will of many hardworking people that it works.
answered Nov 19 '18 at 23:56
Kamil CukKamil Cuk
10.4k1527
10.4k1527
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53384022%2fwhen-do-linux-system-calls-trigger-a-segfault-vs-returning-efault%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I don't believe that a system call can ever segfault. However, glibc can segfault, and a lot of functions that you think are system calls are actually glibc functions.
– immibis
Nov 19 '18 at 23:20