Embed Notice
HTML Code
Corresponding Notice
- Embed this notice
翠星石 (suiseiseki@freesoftwareextremist.com)'s status on Friday, 04-Jul-2025 23:21:04 JST 翠星石
@mia @snacks I was shared this suid binary - it looks bug-free to me?
/* GnuPowerUtils ACPI S3 program
Copyright © 2025 DiffieHellman
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include "shared.h"
int main(int argc, char *argv[])
{
/* print help or version of there are any arguments */
if (argc >= 2){help_or_version(argv[0], argv[1]);}
/* exit(1) if group does not exist or member is not in group */
check_group_membership();
/* change to root user */
if (setuid(0) != 0){error_exit("Suspend binary is not setuid.");}
/* open mem_sleep and state */
int mem_sleep = open("/sys/power/mem_sleep", O_WRONLY);
int state = open("/sys/power/state", O_WRONLY);
if (!mem_sleep || !state){perror_exit("Linux doesn't support Suspend-to-RAM");}
/* write deep to /sys/power/mem_sleep then mem to /sys/power/state to Suspend-to-RAM */
if (write(mem_sleep, "deep\n", 5) != 5){perror_exit("Writing deep failed");}
if (write(state, "mem\n", 4) != 4){perror_exit("Writing mem failed");}
/* close the fd's */
close(mem_sleep);
close(state);
return 0;
}
shared.h:
/* GnuPowerUtils shared functions
Copyright © 2025 DiffieHellman
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <grp.h>
/* definitions and functions that would otherwise be needlessly duplicated between files */
#ifndef GROUP_NAME
#define GROUP_NAME "gnupu"
#endif
#define VERSION "0"
void error_exit(char s[])
{
fprintf(stderr,"%s\n",s);
exit(1);
}
void perror_exit(char s[])
{
perror(s);
exit(1);
}
void check_group_membership()
{
/* get gid of power group and see if user is a member of that gid */
struct group *gnupu = getgrnam(GROUP_NAME);
if (!gnupu){error_exit(GROUP_NAME" group does not exist.\n");}
if (!group_member(gnupu->gr_gid)){error_exit("User is not in "GROUP_NAME" group.\n");}
}
void help_or_version(char z[], char s[])
{
/* no point bothering to use getopt or memcmp */
if (s[0] == '-' && ((s[1] == '-' && s[2] == 'v') || s[1] == 'v'))
{
printf("gnupu (GNU power utils) "VERSION"\n"\
"Copyright © 2025 DiffieHellman\n"\
"License AGPLv3+: GNU AGPL version 3 or later <https://www.gnu.org/licenses/agpl-3.0.html>.\n"\
"This is free software: you are free to change and redistribute it.\n"\
"There is NO WARRANTY, to the extent permitted by law.\n\n"\
"Written by DiffieHellman.\n");
}
else
{
printf("Usage: %s [OPTION]\n"\
"Do power operation on the system\n\n"\
"With no argument, do the operation, otherwise show help or version\n\n"\
"-h, --help show help and exit\n"\
"-v, --version output version information and exit\n\n"\
"Usage:\n"\
"%s Ensure user is in the "GROUP_NAME" group and execute without arguments.\n\n"\
"Documentation: `info gnupu`\n", z, z);
}
exit(0);
}