Disabling SMT (hyperthreading) in ArchLabs


#1

Note: this guide is now obsolete, please apply the nosmt kernel command line parameter to disable hyperthreading.

Some of you may be aware of the recently announced Portsmash vulnerability:

https://www.openwall.com/lists/oss-security/2018/11/01/4

The problem is caused by the design of the cpu, specifically the so-called hyperthreads (symmetric multi-threading technology, or SMT for short) are not subject to the same sort of security checks that are carried out in the physical cores.

OpenBSD 6.4 has disabled SMT by default because of this (the devs predicted the vulnerability) and the advice for Linux is now to disable SMT via the firmware (“BIOS”) settings, if possible.

Unfortunately, my machine has no such option so I have to use systemd unit file instead :slight_smile:

To write the unit we first need to determine which cpu(s) to turn off, so run this command:

empty@buster:~ $ lscpu --extended
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ    MINMHZ
0   0    0      0    0:0:0:0       yes    2400.0000 1199.0000
1   0    0      0    0:0:0:0       yes    2400.0000 1199.0000
2   0    0      1    1:1:1:0       yes    2400.0000 1199.0000
3   0    0      1    1:1:1:0       yes    2400.0000 1199.0000
empty@buster:~ $

^ The CORE column shows which physical cpu is hosting which virtual cpu and in my case cpu1 & cpu3 are hyperthreads and need to be disabled.

To disable them, use this script (saved to /usr/local/bin/nosmt):

#!/bin/sh
for n in 1 3
   do echo 0 > /sys/devices/system/cpu/cpu${n}/online
done

^ Change the for n in 1 3 line according to the hardware in use.

And a matching onsmt script (to re-enable SMT when the .service is stopped):

#!/bin/sh
for n in 1 3
   do echo 1 > /sys/devices/system/cpu/cpu${n}/online
done

Save both of those files and make them executable:

chmod +x /usr/local/bin/{no,on}smt

And this is the systemd custom unit file:

# /etc/systemd/system/nosmt.service
[Unit]
Description=Disable SMT

[Service]
RemainAfterExit=yes
ExecStart=/usr/local/bin/nosmt
ExecStop=/usr/local/bin/onsmt

[Install]
WantedBy=multi-user.target

Once the unit file is saved, enable and start the .service with:

systemctl enable --now nosmt

Check that the hyperthreads have been disabled with lscpu --extended and check the .service with systemctl status nosmt (it should be reported as “active”).

SMT can be enabled again by stopping the .service:

systemctl stop nosmt

If there are any problems, check the journal:

journalctl -u nosmt

#2

so I have to disable 1,3,5,7
it’s right?


[don@don-pc ~]$ grep '^core id' /proc/cpuinfo
core id		: 0
core id		: 0
core id		: 1
core id		: 1
core id		: 2
core id		: 2
core id		: 3
core id		: 3
[don@don-pc ~]$ lscpu --extended
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ    MINMHZ
0   0    0      0    0:0:0:0       si     2401,0000 1200,0000
1   0    0      0    0:0:0:0       si     2401,0000 1200,0000
2   0    0      1    1:1:1:0       si     2401,0000 1200,0000
3   0    0      1    1:1:1:0       si     2401,0000 1200,0000
4   0    0      2    2:2:2:0       si     2401,0000 1200,0000
5   0    0      2    2:2:2:0       si     2401,0000 1200,0000
6   0    0      3    3:3:3:0       si     2401,0000 1200,0000
7   0    0      3    3:3:3:0       si     2401,0000 1200,0000
[don@don-pc ~]$ 

#3

Yes, that’s right :slight_smile:

The second “cpu” on each CORE is virtual rather than physical and so must be using SMT.


#4

@Head_on_a_Stick
Why, this error?

[don@don-pc ~]$ LC_ALL=C 
[don@don-pc ~]$ echo 0 > /sys/devices/system/cpu/cpu{1,3,5,7}/online
bash: /sys/devices/system/cpu/cpu{1,3,5,7}/online: ambiguous redirect
[don@don-pc ~]$ 

#5

Thx for sharing @Head_on_a_Stick


#6

You are trying to redirect into multiple files from one stream, which in bash actually looks like this (note {} expansion is done by the shell before execution)

echo 0 > /sys/devices/system/cpu/cpu1/online /sys/devices/system/cpu/cpu3/online /sys/devices/system/cpu/cpu5/online /sys/devices/system/cpu/cpu7/online

Use a loop instead to avoid this

su -c 'for i in 1 3 5 7; do echo 0 > /sys/devices/system/cpu/cpu${i}/online; done'

#7

^ D’oh! Thanks Nate!

OP corrected…


#8

Thank @natemaia
not working

[[don@don-pc ~]$ for i in 1 3 5 7; do echo '0' > /sys/devices/system/cpu${i}/online; done
bash: /sys/devices/system/cpu1/online: No such file or directory
bash: /sys/devices/system/cpu3/online: No such file or directory
bash: /sys/devices/system/cpu5/online: No such file or directory
bash: /sys/devices/system/cpu7/online: No such file or directory
[don@don-pc ~]$ 

#9

Was a typo, I fixed it right away, but I wasn’t fast enough xD


#10

not working

[don@don-pc ~]$ for i in 1 3 5 7; do echo '0' > /sys/devices/system/cpu/cpu${i}/online; done
bash: /sys/devices/system/cpu/cpu1/online: Permission denied
bash: /sys/devices/system/cpu/cpu3/online: Permission denied
bash: /sys/devices/system/cpu/cpu5/online: Permission denied
bash: /sys/devices/system/cpu/cpu7/online: Permission denied
[don@don-pc ~]$ sudo for i in 1 3 5 7; do echo '0' > /sys/devices/system/cpu/cpu${i}/online; done
bash: syntax error near unexpected token `do'
[don@don-pc ~]$

#12

Try

for i in 1 3 5 7; do sudo bash -c "echo '0' > /sys/devices/system/cpu/cpu${i}/online"; done

Or perhaps

for i in 1 3 5 7; do sudo tee /sys/devices/system/cpu/cpu${i}/online <<< "0"; done

#13

yea, what HoaS said, or use su -c 'loop code'


#14
[don@don-pc ~]$ for i in 1 3 5 7; do echo '0' > /sys/devices/system/cpu/cpu${i}/online; done
bash: /sys/devices/system/cpu/cpu1/online: Permission denied
bash: /sys/devices/system/cpu/cpu3/online: Permission denied
bash: /sys/devices/system/cpu/cpu5/online: Permission denied
bash: /sys/devices/system/cpu/cpu7/online: Permission denied
[don@don-pc ~]$ sudo for i in 1 3 5 7; do echo '0' > /sys/devices/system/cpu/cpu${i}/online; done
bash: syntax error near unexpected token `do'
[don@don-pc ~]$ lscpu --extended
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ    MINMHZ
0   0    0      0    0:0:0:0       si     2401,0000 1200,0000
1   0    0      0    0:0:0:0       si     2401,0000 1200,0000
2   0    0      1    1:1:1:0       si     2401,0000 1200,0000
3   0    0      1    1:1:1:0       si     2401,0000 1200,0000
4   0    0      2    2:2:2:0       si     2401,0000 1200,0000
5   0    0      2    2:2:2:0       si     2401,0000 1200,0000
6   0    0      3    3:3:3:0       si     2401,0000 1200,0000
7   0    0      3    3:3:3:0       si     2401,0000 1200,0000
[don@don-pc ~]$ 

#15
→ $ su -c 'for i in 1 3 5 7; do echo '0' > /sys/devices/system/cpu/cpu${i}/online; done'
Password:
~
→ $


#16

for i in 1 3 5 7; do echo ‘0’ > /sys/devices/system/cpu/cpu${i}/online; done

lscpu --extended

CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ MINMHZ
0 0 0 0 0:0:0:0 yes 3100.0000 800.0000
1 - - - ::: no 3100.0000 800.0000
2 0 0 1 1:1:1:0 yes 3100.0000 800.0000
3 - - - ::: no 3100.0000 800.0000
4 0 0 2 2:2:2:0 yes 3100.0000 800.0000
5 - - - ::: no 3100.0000 800.0000
6 0 0 3 3:3:3:0 yes 3100.0000 800.0000
7 - - - ::: no 3100.0000 800.0000

Edit: thx for this fellas, appreciated.


#17

I’m gonna do mine via the BIOS method as my mobo supports it, we’ll see how it goes without SMT.


#18

To clarify here: the echo command and the > (redirection) both need to be run as root.

EDIT: also, any change made with echo will be lost on the next reboot, the udev rules are needed for persistence.


#19

Yea I was just running to make sure I’m not wrong and it does in fact work with su -c '' :stuck_out_tongue:


#20

Thank at all working,I had to be root

127 root@don-pc /home/don # for i in 1 3 5 7; do echo '0' > /sys/devices/system/cpu/cpu${i}/online; done                                                                                           :(
root@don-pc /home/don # lscpu --extended
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ    MINMHZ
0   0    0      0    0:0:0:0       si     2401,0000 1200,0000
1   -    -      -    :::           no     2401,0000 1200,0000
2   0    0      1    1:1:1:0       si     2401,0000 1200,0000
3   -    -      -    :::           no     2401,0000 1200,0000
4   0    0      2    2:2:2:0       si     2401,0000 1200,0000
5   -    -      -    :::           no     2401,0000 1200,0000
6   0    0      3    3:3:3:0       si     2401,0000 1200,0000
7   -    -      -    :::           no     2401,0000 1200,0000
root@don-pc /home/don # 

#21

Would it be possible for us to see your lscpu --extended output with SMT disabled from the firmware?

I am interested to check if the same cpus are being off-lined. TIA.