Suppress warning: the use of `mktemp' is dangerous
Asked Answered
R

6

12

How can I suppress following warning from gcc linker:

warning: the use of 'mktemp' is dangerous, better use 'mkstemp'

I do know that it's better to use mkstemp() but for some reason I have to use mktemp() function.

Randellrandene answered 12/4, 2009 at 17:37 Comment(4)
Use mkstemp instead of mktemp.Leilaleilah
What is the reason that you have to use mktemp?Leilaleilah
you see this warning when compiling bash gnu.org/software/bashHardy
Also compiling recent glibc produces it :).Secretion
A
10

I guess you need the path because you pass it to a library that only accepts path names as argument and not file descriptors or FILE pointers. If so you can create a temp dir with mkdtemp and place your file there, the actual name is then unimportant because the path is already unique because of the directory.

Archdeaconry answered 12/4, 2009 at 21:44 Comment(3)
You can absolutely STILL use mkstemp: int fd = mkstemp(template); After this call, template will be replaced with the actual file name. You will have the file descriptor and the file's path.Leilaleilah
@Jason Coco you might consider making that an answer, so that it can be upvoted ;-)Joacima
@Jason Coco, ah ok, that sounds reasonable :). I agree with lothar make a answer out of it.Archdeaconry
D
4

If you have to use mktemp then there is not anything you can do to suppress that warning short of removing the section that uses mktemp from libc.so.6.

Why do you have to use mktemp?

Delius answered 12/4, 2009 at 17:48 Comment(0)
C
4

Two things:

  • mktemp is not a standard function
  • the warning is a special one implemented in the linker as .gnu.warning.mktemp section

Use a native OS API if you really need to write to the disk. Or mkstemp() as suggested.

Cress answered 12/4, 2009 at 18:53 Comment(1)
mktemp() is (or was) a standard function. For example in POSIX.1-2001. But don’t use it anyway.Tigges
A
2

Use mkstemp:

int fd = mkstemp(template);

After this call, template will be replaced with the actual file name. You will have the file descriptor and the file's path.

Artiste answered 14/8, 2017 at 18:53 Comment(0)
C
1

If you are statically linking the runtime, then the other option is to write your own version of mktemp in an object file. The linker should prefer your version over the runtime version.

Edit: Thanks to Jason Coco for pointing out a major misunderstanding that I had in mktemp and its relatives. This one is a little easier to solve now. Since the linker will prefer a version in an object file, you just need to write mktemp in terms of mkstemp.

The only difficulties are cleaning up the file descriptors that mkstemp will return to you and making everything thread safe. You could use a static array of descriptors and an atexit-registered function for cleanup if you can put a cap on how many temporary files you need. If not, just use a linked list instead.

Charmer answered 12/4, 2009 at 18:17 Comment(1)
@D: It is an error to provide a constant string to mkstemp or mktemp because the library call will attempt to alter the string and you will get a bus fault.Leilaleilah
P
1

mktemp is frequently misused when the one wants to create a temporary name without actually creating a tmp file, like mkstemp would do. Maybe you want to pass such name to sem_open or shm_open, and you are well aware of an O_EXCL flag. There are many possible uses, when you want to create some object with a random name, and that object is not a tmp file.

However, mktemp really should not be used, even in that case. This is because it checks the generated name over the existing file, and if such file exist, it generates another name, and so on, in a loop. This is really not what you want, especially if you are not going to create such a file at the end.

So it would be better to just write your own implementation targeting your specific needs, rather than to try silencing the mktemp warning. I simply extracted the mktemp generator code from glibc sources and added the %P modifier handling, which adds the pid to a template: https://github.com/dosemu2/dosemu2/blob/devel/src/base/misc/utilities.c#L1103 You can use that code as an example, or just write your own.

There are just the basic caution rules when doing such kind of tricks:

  • Add pid to the object name, in addition to the random chars. That way you avoid a possibility of clashing with another instance of your own program which has the same fixed part of a template.
  • Use O_EXCL when creating an object to avoid any possible malicious attempts to make your program to open something it shouldn't open.
  • If exclusive create failed with EEXIST, an object might be stalled (you have pid in the name, and you know your pid haven't yet created it), so you can unlink it and retry the exclusive creation. If the creation fails again then perhaps something malicious is going on, so you can just exit.
  • Unlink the object as soon as possible, rather than on a program exit. After such objects (semaphores, shared memory etc) are opened, unlink doesn't prevent using them via the already obtained fds. If you want to fork the child process that uses these objects, in most cases it is enough to open them in a parent only, and immediately unlink. The child can use them via the inherited fds, rather than to open again.

I believe the above recommendations are sufficient for making the use of your own mktemp-alike function secure and robust. But that's just my own opinion.

Prendergast answered 14/6, 2023 at 7:42 Comment(4)
All good points, but IMO even all that isn't necessarily secure. Adding the process PID to a temp name isn't going to make it secure - it's trivial for a malicious actor to get the PID. Deleting the object if there's a name collision also seems likely to be exploitable in some form for DOS attacks. Doing this right is hard, which is one reasons why I don't like the semantics of shm_open() and sem_open() - those are prone to TOCTOU-based race conditions and exploits based on the file name.Kaohsiung
Adding the process PID to a temp name isn't going to make it secure - it's needed only to avoid the possibility of clashing with another instance of your own prog, which is an important piece of the puzzle. What makes it secure is O_EXCL, together with the recommendation to never re-open it in a child, but rather use inherited FDs. Name collision is impossible if you follow all the recommendations, except for the case of an orphaned object and a maliciously created one.Prendergast
My concern were directed at the security aspect, especially the possibility of leveraging the delete maliciously. I haven't been able to come up with a way to exploit that, even for a merely-annoying minor DOS attack, but I probably don't have the creative evil of malware writers. I apologize for not making the clear in the first comment.Kaohsiung
If you are creating some rather private resource that you are going to share only with the child process by the fork(), and if you have pid in the object name, then delete is entirely harmless, because it only means that the object got orphaned and the pid (that is also in an object's name) got re-used. Consistently dealing with orphaned objects is important, and any scheme must consider the possibility of an orphaned object.Prendergast

© 2022 - 2024 — McMap. All rights reserved.